library(RPostgres)
wrds <- dbConnect(Postgres(),
                  host='wrds-pgdata.wharton.upenn.edu',
                  port=9737,
                  dbname='wrds',
                  sslmode='require',
                  user='echoi98')
library(tidyverse)
-- Attaching packages --------------------------------------- tidyverse 1.3.0 --
v ggplot2 3.3.0     v purrr   0.3.3
v tibble  2.1.3     v dplyr   0.8.4
v tidyr   1.0.2     v stringr 1.4.0
v readr   1.3.1     v forcats 0.4.0
package 㤼㸱ggplot2㤼㸲 was built under R version 3.6.3-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
library(dbplyr)

Attaching package: 㤼㸱dbplyr㤼㸲

The following objects are masked from 㤼㸱package:dplyr㤼㸲:

    ident, sql

Pull in the companies from crsp to IBES link

link_tool_v1<-read.csv("crsp_ibes_link.csv",header = TRUE)
link_tool_v1<- link_tool_v1%>%filter(SCORE!=6)
link_tool_ticker <- subset(link_tool_v1, select = c('TICKER','NCUSIP','PERMNO'))

Compu stat pull

res <- dbSendQuery(wrds, "select gvkey, datadate, conm,cusip, fyr, fyear, exchg, bkvlps, epsfx, fic from comp.funda
                   where
                   fyr = '12' and 
                   exchg <> 0 and 
                   exchg <> 1 and
                   exchg <> 19 and
                   popsrc = 'D' and 
                   consol = 'C' and 
                   datafmt = 'STD'")
compustat_data <- dbFetch(res, n=-1)
dbClearResult(res)
head(compustat_data)
   gvkey   datadate                  conm     cusip fyr fyear exchg bkvlps epsfx fic
1 001000 1961-12-31 A & E PLASTIK PAK INC 000032102  12  1961    12 2.4342    NA USA
2 001000 1962-12-31 A & E PLASTIK PAK INC 000032102  12  1962    12 3.0497    NA USA
3 001000 1963-12-31 A & E PLASTIK PAK INC 000032102  12  1963    12 2.9731    NA USA
4 001000 1964-12-31 A & E PLASTIK PAK INC 000032102  12  1964    12 3.0969    NA USA
5 001000 1965-12-31 A & E PLASTIK PAK INC 000032102  12  1965    12 2.3835    NA USA
6 001000 1966-12-31 A & E PLASTIK PAK INC 000032102  12  1966    12 3.8082    NA USA

Clean Compustat Data

compustat_data_v1<-compustat_data
compustat_data_v1<- compustat_data_v1%>%drop_na(bkvlps)

Grab the Security files for compustat for us first

res <- dbSendQuery(wrds, "select gvkey, ibtic from comp.security")
compustat_security_data <- dbFetch(res, n=-1)
dbClearResult(res)

Take out any NA’s in compustat security

compustat_security_data_v1<-compustat_security_data
compustat_security_data_v1<- compustat_security_data_v1%>%drop_na(ibtic)
head(compustat_security_data_v1)
    gvkey ibtic
2  001001  AMFD
4  001003  ANTQ
5  001004   AIR
10 001009  ABSI
12 001011  ACSE
14 001013  ADCT

Grab the Security files for compustat for global first

res <- dbSendQuery(wrds, "select gvkey, ibtic from comp.g_security")
compustat_global_security_data <- dbFetch(res, n=-1)
dbClearResult(res)

Take out any NA’s in global compustat security

compustat_global_security_data_v1<-compustat_global_security_data
compustat_global_security_data_v1<- compustat_global_security_data_v1%>%drop_na(ibtic)
head(compustat_global_security_data_v1)
    gvkey ibtic
1  001166   @4M
5  001491  @A3I
6  001661  @66K
8  001855   @AT
9  001855  @YZV
10 001932  @BAT

Save this data to an excel

write.csv(compustat_data_v3,"compustat_data_vf.csv")

IBES pull ################################################################################################################################################################################################################################## Pull International IBES Summary Data

res <- dbSendQuery(wrds, "select ticker, cusip,cname,fiscalp,statpers,actual, anndats_act, actdats_act,numest,meanest, medest,fpedats,usfirm, fpi from ibes.NSTATSUM_EPSINT
                   where fiscalp = 'ANN' 
                   ")
ibes_int_stat_sum_data <- dbFetch(res, n=-1)
dbClearResult(res)
head(ibes_int_stat_sum_data)
  ticker    cusip           cname fiscalp   statpers actual anndats_act actdats_act numest meanest medest    fpedats usfirm fpi
1   0003 66515910 NORTHN FRONTIER     ANN 2014-04-17  -0.16  2015-03-19  2015-03-19      4    0.22   0.22 2014-12-31      0   1
2   0003 66515910 NORTHN FRONTIER     ANN 2014-05-15  -0.16  2015-03-19  2015-03-19      4    0.22   0.22 2014-12-31      0   1
3   0003 66515910 NORTHN FRONTIER     ANN 2014-06-19  -0.16  2015-03-19  2015-03-19      4    0.19   0.17 2014-12-31      0   1
4   0003 66515910 NORTHN FRONTIER     ANN 2014-07-17  -0.16  2015-03-19  2015-03-19      4    0.08   0.11 2014-12-31      0   1
5   0003 66515910 NORTHN FRONTIER     ANN 2014-08-14  -0.16  2015-03-19  2015-03-19      4    0.08   0.11 2014-12-31      0   1
6   0003 66515910 NORTHN FRONTIER     ANN 2014-09-18  -0.16  2015-03-19  2015-03-19      4   -0.02  -0.04 2014-12-31      0   1

Pull US IBES Summary Data

res <- dbSendQuery(wrds, "select ticker, cusip,cname,fiscalp,statpers,actual, anndats_act, actdats_act,numest,meanest, medest,fpedats,usfirm,fpi from ibes.NSTATSUM_EPSUs
                   where fiscalp = 'ANN' and 
                   numest >=1
                   ")
ibes_US_stat_sum_data <- dbFetch(res, n=-1)
dbClearResult(res)
head(ibes_US_stat_sum_data)
  ticker    cusip          cname fiscalp   statpers actual anndats_act actdats_act numest meanest medest    fpedats usfirm fpi
1   0000 87482X10 TALMER BANCORP     ANN 2014-04-17   1.21  2015-01-30  2015-01-30      4    0.52   0.51 2014-12-31      1   1
2   0000 87482X10 TALMER BANCORP     ANN 2014-05-15   1.21  2015-01-30  2015-01-30      4    0.56   0.58 2014-12-31      1   1
3   0000 87482X10 TALMER BANCORP     ANN 2014-06-19   1.21  2015-01-30  2015-01-30      4    0.56   0.58 2014-12-31      1   1
4   0000 87482X10 TALMER BANCORP     ANN 2014-07-17   1.21  2015-01-30  2015-01-30      3    0.56   0.58 2014-12-31      1   1
5   0000 87482X10 TALMER BANCORP     ANN 2014-08-14   1.21  2015-01-30  2015-01-30      5    1.18   1.17 2014-12-31      1   1
6   0000 87482X10 TALMER BANCORP     ANN 2014-09-18   1.21  2015-01-30  2015-01-30      4    1.17   1.17 2014-12-31      1   1

Merger both ibes together

complete_ibes_data<-rbind(ibes_int_stat_sum_data, ibes_US_stat_sum_data)
head(complete_ibes_data)
  ticker    cusip           cname fiscalp   statpers actual anndats_act actdats_act numest meanest medest    fpedats usfirm fpi
1   0003 66515910 NORTHN FRONTIER     ANN 2014-04-17  -0.16  2015-03-19  2015-03-19      4    0.22   0.22 2014-12-31      0   1
2   0003 66515910 NORTHN FRONTIER     ANN 2014-05-15  -0.16  2015-03-19  2015-03-19      4    0.22   0.22 2014-12-31      0   1
3   0003 66515910 NORTHN FRONTIER     ANN 2014-06-19  -0.16  2015-03-19  2015-03-19      4    0.19   0.17 2014-12-31      0   1
4   0003 66515910 NORTHN FRONTIER     ANN 2014-07-17  -0.16  2015-03-19  2015-03-19      4    0.08   0.11 2014-12-31      0   1
5   0003 66515910 NORTHN FRONTIER     ANN 2014-08-14  -0.16  2015-03-19  2015-03-19      4    0.08   0.11 2014-12-31      0   1
6   0003 66515910 NORTHN FRONTIER     ANN 2014-09-18  -0.16  2015-03-19  2015-03-19      4   -0.02  -0.04 2014-12-31      0   1

Rename the columns

complete_ibes_data_v1<-complete_ibes_data
complete_ibes_data_v1<-rename(complete_ibes_data_v1,forecast_date=statpers, actual_earnings=actual, forecasted_period=fpedats)
complete_ibes_data_v1<-complete_ibes_data_v1%>%group_by(ticker)
complete_ibes_data_v1

Only get fiscal year 12 end, forecast period of 1 (FPI) and take out nas

complete_ibes_data_v2<-complete_ibes_data_v1
# Month where the analyst forecasted
complete_ibes_data_v2$fiscal_year_end_month <- format(complete_ibes_data_v2$forecasted_period,"%m")
complete_ibes_data_v2<-complete_ibes_data_v2%>%filter(fiscal_year_end_month==12)
complete_ibes_data_v2<-complete_ibes_data_v2%>% filter(fpi==1)
complete_ibes_data_v2<-complete_ibes_data_v2%>% drop_na(actual_earnings)

Find the largest forecast date for any given forecast year

largest_forecast_date_max <- complete_ibes_data_v2%>%group_by(ticker,forecasted_period)%>%summarise(max=max(forecast_date))
largest_forecast_date_min <- complete_ibes_data_v2%>%group_by(ticker,forecasted_period)%>%summarise(min=min(forecast_date))
largest_forecast_date_max
largest_forecast_date_min

Create IBES consensus forecast database

ibes_forecast_first_forecast<-inner_join(complete_ibes_data_v2,largest_forecast_date_min,by=c('ticker'='ticker','forecasted_period'='forecasted_period','forecast_date'='min'))
ibes_forecast_last_forecast<-inner_join(complete_ibes_data_v2,largest_forecast_date_max,by=c('ticker'='ticker','forecasted_period'='forecasted_period','forecast_date'='max'))
ibes_forecast_first_forecast
ibes_forecast_last_forecast

Column comparison of beat or loss

# Using Mean Estimates for the first earnings forecast date recorded
ibes_forecast_first_forecast$above_expectations_mean<-0
ibes_forecast_first_forecast$below_expectations_mean <-0
ibes_forecast_first_forecast$above_expectations_mean[ibes_forecast_first_forecast$actual_earnings>ibes_forecast_first_forecast$meanest]<-1
ibes_forecast_first_forecast$below_expectations_mean[ibes_forecast_first_forecast$above_expectations_mean==0]<-1
# Using Median Estimates for the first earnings forecast date recorded
ibes_forecast_first_forecast$above_expectations_median<-0
ibes_forecast_first_forecast$below_expectations_median <-0
ibes_forecast_first_forecast$above_expectations_median[ibes_forecast_first_forecast$actual_earnings>ibes_forecast_first_forecast$medest]<-1
ibes_forecast_first_forecast$below_expectations_median[ibes_forecast_first_forecast$above_expectations_median==0]<-1
# Using Mean Estimates for the last earnings forecast date recorded
ibes_forecast_last_forecast$above_expectations_mean<-0
ibes_forecast_last_forecast$below_expectations_mean <-0
ibes_forecast_last_forecast$above_expectations_mean[ibes_forecast_last_forecast$actual_earnings>ibes_forecast_last_forecast$meanest]<-1
ibes_forecast_last_forecast$below_expectations_mean[ibes_forecast_last_forecast$above_expectations_mean==0]<-1
# Using Median Estimates for the last earnings forecast date recorded
ibes_forecast_last_forecast$above_expectations_median<-0
ibes_forecast_last_forecast$below_expectations_median <-0
ibes_forecast_last_forecast$above_expectations_median[ibes_forecast_last_forecast$actual_earnings>ibes_forecast_last_forecast$medest]<-1
ibes_forecast_last_forecast$below_expectations_median[ibes_forecast_last_forecast$above_expectations_median==0]<-1
ibes_forecast_first_forecast
ibes_forecast_last_forecast

Save these IBES forecasts

write.csv(ibes_forecast_first_forecast_linked,"ibes_forecast_first_forecast_linked.csv")
write.csv(ibes_forecast_last_forecast_linked,"ibes_forecast_last_forecast_linked.csv")

CRSP data ##################################################################################################################################################################################################################################

# hexcd 1 = NYSE, hexcd 2 = AMEX, hexcd 3 = NASDAQ 
res <- dbSendQuery(wrds, "select date,permno,cusip,prc, ret, vol, shrout ,hexcd, cfacpr from crspa.msf
                   where prc >0")
crsp_data <- dbFetch(res, n=-1)
dbClearResult(res)

Adjust the price and omit nas

col_order <- c("date","year", "month", "permno","cusip", "price","monthly_returns","volume","shares_outstanding","market_capitalization","exchange")
# Omit all rows with incomplete data
crsp_data_v1<-crsp_data%>%drop_na(cfacpr,vol,prc,shrout,ret)
# Adjust Price by price adjustment factor 
crsp_data_v1$prc <- abs(crsp_data_v1$prc)/crsp_data_v1$cfacpr
head(crsp_data_v1)
        date permno    cusip      prc          ret vol shrout hexcd cfacpr
1 1986-09-30  10001 36720410 2.125000 -0.003076924 366    991     2      3
2 1986-10-31  10001 36720410 2.208333  0.039215688 362    991     2      3
3 1986-11-28  10001 36720410 2.333333  0.056603774 312    991     2      3
4 1986-12-31  10001 36720410 2.333333  0.015000000 312    991     2      3
5 1987-01-30  10001 36720410 2.250000 -0.035714287 399    991     2      3
6 1987-02-27  10001 36720410 2.083333 -0.074074075 365    991     2      3

Get price as of the last day of april

crsp_data_v3<-crsp_data_v2
crsp_data_v3$price_month <- format(crsp_data_v3$date,"%m")
crsp_data_v3<-crsp_data_v3%>%filter(price_month=='04')
head(crsp_data_v3)
        date permno    cusip      prc         ret vol shrout hexcd cfacpr TICKER   NCUSIP price_month
1 1989-04-28  10001 36720410 2.416667  0.07407407 310    998     2      3   GFGC 39040610          04
2 1989-04-28  10001 36720410 2.416667  0.07407407 310    998     2      3   GFGC 29274A10          04
3 1989-04-28  10001 36720410 2.416667  0.07407407 310    998     2      3   GFGC 29274A20          04
4 1989-04-28  10001 36720410 2.416667  0.07407407 310    998     2      3   GFGC 29269V10          04
5 1989-04-28  10001 36720410 2.416667  0.07407407 310    998     2      3   GFGC 36720410          04
6 1994-04-29  10001 36720410 4.916667 -0.14492753 102   1091     2      3   GFGC 39040610          04

Screen to only get one entry per permno per date

crsp_data_v4<-crsp_data_v3
crsp_data_v4<-crsp_data_v4%>%distinct(permno,date,.keep_all = TRUE)
crsp_data_v4<-crsp_data_v4%>%group_by(permno)
crsp_data_v4

save this csv

write.csv(crsp_data_v4, "crsp_data_vf.csv")

Now we want to merge the three databases to form our quartiles ##################################################################################################################################################################################################################################

compustat_data<-read.csv("compustat_data_vf.csv",header = TRUE)
crsp_data<-read.csv("crsp_data_vf.csv",header = TRUE)
IBES_data<-read.csv("ibes_forecast_last_forecast_linked.csv", header=TRUE)
compustat_data<-compustat_data%>%group_by(gvkey)
crsp_data<-crsp_data%>%group_by(permno)
IBES_data<-IBES_data%>%group_by(ticker)
compustat_data
crsp_data
IBES_data

Get only the columns we want from each table

# Take the columsn we need
columns<-c('fyear','ibtic','NCUSIP','PERMNO','bkvlps','epsfx')
modified_compustat_data<-compustat_data[,columns]
columns<-c('date','permno','prc','TICKER')
modified_crsp_data<-crsp_data[,columns]
columns<-c('ticker','PERMNO','cname','forecast_date','actual_earnings','forecasted_period','above_expectations_mean','above_expectations_median','below_expectations_mean','below_expectations_median','numest')
modified_ibes_data<-IBES_data[,columns]
modified_compustat_data
modified_crsp_data
modified_ibes_data

Get the fiscl year prior

modified_crsp_data$date<-as.Date(modified_crsp_data$date)
modified_crsp_data$year<- format(modified_crsp_data$date,"%Y")
modified_crsp_data$year<-as.numeric(modified_crsp_data$year)
modified_crsp_data$previous_year<-modified_crsp_data$year-1
columns<-c('permno','TICKER','date','prc', 'previous_year')
modified_crsp_data<-modified_crsp_data[,columns]
modified_crsp_data

Merge Crsp and Compustat

merged_crsp_compustat<-inner_join(modified_compustat_data,modified_crsp_data,by=c('PERMNO'='permno', 'ibtic'='TICKER','fyear'='previous_year'))
Column `ibtic`/`TICKER` joining factors with different levels, coercing to character vector
merged_crsp_compustat<-merged_crsp_compustat%>%drop_na(epsfx)
merged_crsp_compustat$PE_Ratio<-merged_crsp_compustat$prc/merged_crsp_compustat$epsfx
merged_crsp_compustat$PB_Ratio<-merged_crsp_compustat$prc/merged_crsp_compustat$bkvlps
merged_crsp_compustat

Quartile the data on PB and PE

merged_crsp_compustat<-merged_crsp_compustat%>%group_by(fyear)%>%mutate(quartile_PE_ratio=ntile(PE_Ratio,4))
merged_crsp_compustat<-merged_crsp_compustat%>%group_by(fyear)%>%mutate(quartile_PB_ratio=ntile(PB_Ratio,4))
# Take only the top and bottom quartiles
merged_crsp_compustat<-merged_crsp_compustat%>%filter(quartile_PE_ratio==4|quartile_PE_ratio==1|quartile_PB_ratio==4|quartile_PB_ratio==1)
# Set up dummies if Price to book value 
merged_crsp_compustat$value_stock_PB<-0
merged_crsp_compustat$value_stock_PB[merged_crsp_compustat$quartile_PB_ratio==1]<-1
# Set up dummies if Price to Earnings value 
merged_crsp_compustat$value_stock_PE<-0
merged_crsp_compustat$value_stock_PE[merged_crsp_compustat$quartile_PE_ratio==1]<-1
# Set up dummies if Price to book value 
merged_crsp_compustat$growth_stock_PB<-1
merged_crsp_compustat$growth_stock_PB[merged_crsp_compustat$value_stock_PB==1]<-0
# Set up dummies if Price to book value 
merged_crsp_compustat$growth_stock_PE<-1
merged_crsp_compustat$growth_stock_PE[merged_crsp_compustat$value_stock_PE==1]<-0
merged_crsp_compustat

Take the columns we need to prep for merge to ibes

# Get the columns we need
columns<-c('ibtic','PERMNO','fyear','date','value_stock_PB','value_stock_PE','growth_stock_PB','growth_stock_PE')
merged_crsp_compustat_modified<-merged_crsp_compustat[,columns]
merged_crsp_compustat_modified
# Prep IBES to get out fiscal year prediction
modified_ibes_data$forecasted_period<-as.Date(modified_ibes_data$forecasted_period)
modified_ibes_data$year<- format(modified_ibes_data$forecasted_period,"%Y")
columns<-c('ticker','PERMNO','year','cname','above_expectations_mean','above_expectations_median','below_expectations_mean','below_expectations_median','numest')
modified_ibes_data<-modified_ibes_data[,columns]
modified_ibes_data

Merge to ibes

# Covert char to numeric
modified_ibes_data$year<-as.numeric(modified_ibes_data$year)
consolidated_crsp_compustat_ibes<-inner_join(merged_crsp_compustat_modified,modified_ibes_data, by = c('fyear'='year','ibtic'='ticker','PERMNO'='PERMNO'))
Column `ibtic`/`ticker` joining character vector and factor, coercing into character vector
consolidated_crsp_compustat_ibes<-consolidated_crsp_compustat_ibes%>%distinct(ibtic,PERMNO,fyear,date,.keep_all=TRUE)
consolidated_crsp_compustat_ibes

Organize and clean the database

columns<-c('ibtic','PERMNO','cname','fyear','date','value_stock_PB','value_stock_PE','growth_stock_PB','growth_stock_PE','above_expectations_median','below_expectations_mean','below_expectations_median')
consolidated_crsp_compustat_ibes_vf<-consolidated_crsp_compustat_ibes
consolidated_crsp_compustat_ibes_vf<-consolidated_crsp_compustat_ibes_vf[,columns]
consolidated_crsp_compustat_ibes_vf<-rename(consolidated_crsp_compustat_ibes_vf,IBES_Ticker_ID=ibtic, CRSP_Permno_ID=PERMNO,Fiscal_Year=fyear,Stock_Price_Date=date,Company_Name=cname)
consolidated_crsp_compustat_ibes_vf

Save the consolidate data

write.csv(consolidated_crsp_compustat_ibes_vf,"consolidated_crsp_compustat_ibes_vf.csv")

Now we want to get 90 day return and then one year return on the stock ##################################################################################################################################################################################################################################

columns<-c('IBES_Ticker_ID','CRSP_Permno_ID','Company_Name','Fiscal_Year','Stock_Price_Date')
forward_dates<-consolidated_crsp_compustat_ibes_vf[,columns]
forward_dates$date_add_90<-forward_dates$Stock_Price_Date+90
forward_dates$date_add_one_year<-forward_dates$Stock_Price_Date+365
forward_dates$quarter_month<-format(forward_dates$date_add_90,"%m")
forward_dates$quarter_year<-format(forward_dates$date_add_90,"%Y")
forward_dates$future_month<-format(forward_dates$date_add_one_year,"%m")
forward_dates$future_year<-format(forward_dates$date_add_one_year,"%Y")
forward_dates

Get the crsp price data again

# hexcd 1 = NYSE, hexcd 2 = AMEX, hexcd 3 = NASDAQ 
res <- dbSendQuery(wrds, "select date,permno,prc, cfacpr from crspa.msf
                   where prc >0")
crsp_price_data <- dbFetch(res, n=-1)
dbClearResult(res)
head(crsp_price_data)
        date permno   prc cfacpr
1 1986-09-30  10001 6.375      3
2 1986-10-31  10001 6.625      3
3 1986-11-28  10001 7.000      3
4 1986-12-31  10001 7.000      3
5 1987-01-30  10001 6.750      3
6 1987-02-27  10001 6.250      3

Now we only wnat to keep price that are relevant

crsp_price_data_v1<-crsp_price_data
crsp_price_data_v1<-crsp_price_data_v1%>%group_by(permno)
crsp_price_data_v1<-crsp_price_data_v1%>%drop_na(prc)
# Modify the price
crsp_price_data_v1$prc <- abs(crsp_price_data_v1$prc)/crsp_price_data_v1$cfacpr
# Break out the date 
crsp_price_data_v1$month<-format(crsp_price_data_v1$date,"%m")
crsp_price_data_v1$year<-format(crsp_price_data_v1$date,"%Y")
crsp_price_data_v1

Clean up both sets

# Clean up pulled crsp data
columns<-c('date','permno','prc','month','year')
crsp_price_data_v2<-crsp_price_data_v1[,columns]
# Partition forward dates table
columns<-c('CRSP_Permno_ID','Stock_Price_Date','quarter_month','quarter_year','future_month','future_year')
forward_dates_v2<-forward_dates[,columns]
crsp_price_data_v2
forward_dates_v2

Join to get full data

original_security_price<-inner_join(forward_dates_v2,crsp_price_data_v2,by=c('CRSP_Permno_ID'='permno','Stock_Price_Date'='date'))
columns<-c('CRSP_Permno_ID','Stock_Price_Date','prc')
original_security_price<-original_security_price[,columns]
future_quarter_security_price<-inner_join(forward_dates_v2,crsp_price_data_v2,by=c('CRSP_Permno_ID'='permno','quarter_month'='month','quarter_year'='year'))
columns<-c('CRSP_Permno_ID','Stock_Price_Date','prc')
future_quarter_security_price<-future_quarter_security_price[,columns]
future_quarter_security_price<-rename(future_quarter_security_price,quarter_after_price=prc)
future_year_security_price<-inner_join(forward_dates_v2,crsp_price_data_v2,by=c('CRSP_Permno_ID'='permno','future_month'='month','future_year'='year'))
columns<-c('CRSP_Permno_ID','Stock_Price_Date','prc')
future_year_security_price<-future_year_security_price[,columns]
future_year_security_price<-rename(future_year_security_price,year_after_price=prc)
original_security_price
future_quarter_security_price
future_year_security_price

Join to get all of these price data together

consolidated_pricing_data<-inner_join(original_security_price, future_quarter_security_price,by=c('CRSP_Permno_ID'='CRSP_Permno_ID','Stock_Price_Date'='Stock_Price_Date'))
consolidated_pricing_data<-inner_join(consolidated_pricing_data, future_year_security_price,by=c('CRSP_Permno_ID'='CRSP_Permno_ID','Stock_Price_Date'='Stock_Price_Date'))
consolidated_pricing_data$quarter_after_return<-consolidated_pricing_data$quarter_after_price/consolidated_pricing_data$prc-1
consolidated_pricing_data$annual_after_return<-consolidated_pricing_data$year_after_price/consolidated_pricing_data$prc-1
columns<-c("CRSP_Permno_ID","Stock_Price_Date",'quarter_after_return','annual_after_return')
consolidated_pricing_data<-consolidated_pricing_data[,columns]
consolidated_pricing_data

Save this CSV

write.csv(consolidated_pricing_data,"consolidated_pricing_data.csv")

Merge Pricing back to our original csv ##################################################################################################################################################################################################################################

consolidated_crsp_compustat_ibes_vf
consolidated_pricing_data
consolidated_data_vf<-inner_join(consolidated_crsp_compustat_ibes_vf,consolidated_pricing_data,by=c('CRSP_Permno_ID'='CRSP_Permno_ID','Stock_Price_Date'='Stock_Price_Date'))
consolidated_data_vf

Write this into csv format

write.csv(consolidated_data_vf,"consolidated_data_vf.csv")

Look at YOY Returns ##################################################################################################################################################################################################################################

Group by year and value and above by median

# Using Price to Book
value_by_price_to_book_perform_above<-consolidated_data_vf%>%filter(value_stock_PB==1 & above_expectations_median==1)
There were 50 or more warnings (use warnings() to see the first 50)
value_by_price_to_book_perform_below<-consolidated_data_vf%>%filter(value_stock_PB==1 & above_expectations_median==0)
growth_by_price_to_book_perform_above<-consolidated_data_vf%>%filter(growth_stock_PB==1& above_expectations_median==1)
growth_by_price_to_book_perform_below<-consolidated_data_vf%>%filter(growth_stock_PB==1 & above_expectations_median==0)
# Using Price to Earnings
value_by_price_to_earnings_perform_above<-consolidated_data_vf%>%filter(value_stock_PE==1 & above_expectations_median==1)
value_by_price_to_earnings_perform_below<-consolidated_data_vf%>%filter(value_stock_PE==1 & above_expectations_median==0)
growth_by_price_to_earnings_perform_above<-consolidated_data_vf%>%filter(growth_stock_PE==1 & above_expectations_median==1)
growth_by_price_to_earnings_perform_below<-consolidated_data_vf%>%filter(growth_stock_PE==1 & above_expectations_median==0)
#Get the average return per year above, PB value
value_by_price_to_book_perform_above$average_quaterly_return<-mean(value_by_price_to_book_perform_above$quarter_after_return)
value_by_price_to_book_perform_above$average_annual_return<-mean(value_by_price_to_book_perform_above$annual_after_return)
#Get the average return per year below, PB value
value_by_price_to_book_perform_below$average_quaterly_return<-mean(value_by_price_to_book_perform_below$quarter_after_return)
value_by_price_to_book_perform_below$average_annual_return<-mean(value_by_price_to_book_perform_below$annual_after_return)
#Get the average return per year above, PB Growth
growth_by_price_to_book_perform_above$average_quaterly_return<-mean(growth_by_price_to_book_perform_above$quarter_after_return)
growth_by_price_to_book_perform_above$average_annual_return<-mean(growth_by_price_to_book_perform_above$annual_after_return)
#Get the average return per year below, PB Growth
growth_by_price_to_book_perform_below$average_quaterly_return<-mean(growth_by_price_to_book_perform_below$quarter_after_return)
growth_by_price_to_book_perform_below$average_annual_return<-mean(growth_by_price_to_book_perform_below$annual_after_return)
#Get the average return per year above, PE value
value_by_price_to_earnings_perform_above$average_quaterly_return<-mean(value_by_price_to_earnings_perform_above$quarter_after_return)
value_by_price_to_earnings_perform_above$average_annual_return<-mean(value_by_price_to_earnings_perform_above$annual_after_return)
#Get the average return per year below, PB value
value_by_price_to_earnings_perform_below$average_quaterly_return<-mean(value_by_price_to_earnings_perform_below$quarter_after_return)
value_by_price_to_earnings_perform_below$average_annual_return<-mean(value_by_price_to_earnings_perform_below$annual_after_return)
#Get the average return per year above, PB Growth
growth_by_price_to_earnings_perform_above$average_quaterly_return<-mean(growth_by_price_to_earnings_perform_above$quarter_after_return)
growth_by_price_to_earnings_perform_above$average_annual_return<-mean(growth_by_price_to_earnings_perform_above$annual_after_return)
#Get the average return per year below, PB Growth
growth_by_price_to_earnings_perform_below$average_quaterly_return<-mean(growth_by_price_to_earnings_perform_below$quarter_after_return)
growth_by_price_to_earnings_perform_below$average_annual_return<-mean(growth_by_price_to_earnings_perform_below$annual_after_return)
#Output Results P/B
value_by_price_to_book_perform_above
value_by_price_to_book_perform_below
growth_by_price_to_book_perform_above
growth_by_price_to_book_perform_below
#Output Results P/E
value_by_price_to_earnings_perform_above
value_by_price_to_earnings_perform_below
growth_by_price_to_earnings_perform_above
growth_by_price_to_earnings_perform_below

Concat this to get just one value

value_by_price_to_book_perform_above_summary<-value_by_price_to_book_perform_above%>%distinct(Fiscal_Year,.keep_all = TRUE)
value_by_price_to_book_perform_below_summary<-value_by_price_to_book_perform_below%>%distinct(Fiscal_Year,.keep_all = TRUE)
growth_by_price_to_book_perform_above_summary<-growth_by_price_to_book_perform_above%>%distinct(Fiscal_Year,.keep_all = TRUE)
growth_by_price_to_book_perform_below_summary<-growth_by_price_to_book_perform_below%>%distinct(Fiscal_Year,.keep_all = TRUE)
value_by_price_to_book_perform_above_summary<-arrange(value_by_price_to_book_perform_above_summary,Fiscal_Year)
value_by_price_to_book_perform_below_summary<-arrange(value_by_price_to_book_perform_below_summary,Fiscal_Year)
growth_by_price_to_book_perform_above_summary<-arrange(growth_by_price_to_book_perform_above_summary,Fiscal_Year)
growth_by_price_to_book_perform_below_summary<-arrange(growth_by_price_to_book_perform_below_summary,Fiscal_Year)
aggregate_price_to_book<-rbind(value_by_price_to_book_perform_above_summary,value_by_price_to_book_perform_below_summary,growth_by_price_to_book_perform_above_summary,growth_by_price_to_book_perform_below_summary)
aggregate_price_to_book<-aggregate_price_to_book%>%group_by(Fiscal_Year)
aggregate_price_to_book<-arrange(aggregate_price_to_book,Fiscal_Year)
value_by_price_to_book_perform_above_summary

Concat this to get just one value

value_by_price_to_earnings_perform_above_summary<-value_by_price_to_earnings_perform_above%>%distinct(Fiscal_Year,.keep_all = TRUE)
value_by_price_to_earnings_perform_below_summary<-value_by_price_to_earnings_perform_below%>%distinct(Fiscal_Year,.keep_all = TRUE)
growth_by_price_to_earnings_perform_above_summary<-growth_by_price_to_earnings_perform_above%>%distinct(Fiscal_Year,.keep_all = TRUE)
growth_by_price_to_earnings_perform_below_summary<-growth_by_price_to_earnings_perform_below%>%distinct(Fiscal_Year,.keep_all = TRUE)
value_by_price_to_earnings_perform_above_summary<-arrange(value_by_price_to_earnings_perform_above_summary,Fiscal_Year)
value_by_price_to_earnings_perform_below_summary<-arrange(value_by_price_to_earnings_perform_below_summary,Fiscal_Year)
growth_by_price_to_earnings_perform_above_summary<-arrange(growth_by_price_to_earnings_perform_above_summary,Fiscal_Year)
growth_by_price_to_earnings_perform_below_summary<-arrange(growth_by_price_to_earnings_perform_below_summary,Fiscal_Year)
aggregate_price_to_earnings<-rbind(value_by_price_to_earnings_perform_above_summary,value_by_price_to_earnings_perform_below_summary,growth_by_price_to_earnings_perform_above_summary,growth_by_price_to_earnings_perform_below_summary)
aggregate_price_to_earnings<-aggregate_price_to_earnings%>%group_by(Fiscal_Year)
aggregate_price_to_earnings<-arrange(aggregate_price_to_earnings,Fiscal_Year)
aggregate_price_to_earnings

Make a for aggregate returns given price to earnings

aggregate_price_to_earnings$type_of_security_PB<-"NA"
aggregate_price_to_earnings$type_of_security_PB[aggregate_price_to_earnings$value_stock_PB==1&aggregate_price_to_earnings$above_expectations_median==1]<-"Value Stock Above Expectations"
aggregate_price_to_earnings$type_of_security_PB[aggregate_price_to_earnings$value_stock_PB==1&aggregate_price_to_earnings$above_expectations_median==0]<-"Value Stock Below Expectations"
aggregate_price_to_earnings$type_of_security_PB[aggregate_price_to_earnings$growth_stock_PB==1&aggregate_price_to_earnings$above_expectations_median==1]<-"Growth Stock Above Expectations"
aggregate_price_to_earnings$type_of_security_PB[aggregate_price_to_earnings$growth_stock_PB==1&aggregate_price_to_earnings$above_expectations_median==0]<-"Growth Stock Below Expectations"
aggregate_price_to_earnings$type_of_security_PE<-"NA"
aggregate_price_to_earnings$type_of_security_PE[aggregate_price_to_earnings$value_stock_PE==1&aggregate_price_to_earnings$above_expectations_median==1]<-"Value Stock Above Expectations"
aggregate_price_to_earnings$type_of_security_PE[aggregate_price_to_earnings$growth_stock_PE==1&aggregate_price_to_earnings$above_expectations_median==1]<-"Growth Stock Above Expectations"
aggregate_price_to_earnings$type_of_security_PE[aggregate_price_to_earnings$value_stock_PE==1&aggregate_price_to_earnings$above_expectations_median==0]<-"Value Stock Below Expectations"
aggregate_price_to_earnings$type_of_security_PE[aggregate_price_to_earnings$growth_stock_PE==1&aggregate_price_to_earnings$above_expectations_median==0]<-"Growth Stock Below Expectations"

Mutate the data so we can work with it

columns<-c('Fiscal_Year','quarter_after_return','annual_after_return','type_of_security_PB','type_of_security_PE')
aggregate_price_to_earnings_v1<-aggregate_price_to_earnings[,columns]
aggregate_price_to_earnings_v1

Write into Excel

write.csv(value_by_price_to_book_perform_above_summary,"value_by_price_to_book_perform_above_summary.csv")
write.csv(value_by_price_to_book_perform_below_summary,"value_by_price_to_book_perform_below_summary.csv")
write.csv(growth_by_price_to_book_perform_above_summary,"growth_by_price_to_book_perform_above_summary.csv")
write.csv(growth_by_price_to_book_perform_below_summary,"growth_by_price_to_book_perform_below_summary.csv")
write.csv(value_by_price_to_earnings_perform_above_summary,"value_by_price_to_earnings_perform_above_summary.csv")
write.csv(value_by_price_to_earnings_perform_below_summary,"value_by_price_to_earnings_perform_below_summary.csv")
write.csv(growth_by_price_to_earnings_perform_above_summary,"growth_by_price_to_earnings_perform_above_summary.csv")
write.csv(growth_by_price_to_earnings_perform_below_summary,"growth_by_price_to_earnings_perform_below_summary.csv")
LS0tDQp0aXRsZTogIkdlb3JnZSBOZXcgUHJvamVjdCINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCmBgYHtyfQ0KbGlicmFyeShSUG9zdGdyZXMpDQp3cmRzIDwtIGRiQ29ubmVjdChQb3N0Z3JlcygpLA0KICAgICAgICAgICAgICAgICAgaG9zdD0nd3Jkcy1wZ2RhdGEud2hhcnRvbi51cGVubi5lZHUnLA0KICAgICAgICAgICAgICAgICAgcG9ydD05NzM3LA0KICAgICAgICAgICAgICAgICAgZGJuYW1lPSd3cmRzJywNCiAgICAgICAgICAgICAgICAgIHNzbG1vZGU9J3JlcXVpcmUnLA0KICAgICAgICAgICAgICAgICAgdXNlcj0nZWNob2k5OCcpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoZGJwbHlyKQ0KYGBgDQpQdWxsIGluIHRoZSBjb21wYW5pZXMgZnJvbSBjcnNwIHRvIElCRVMgbGluayANCmBgYHtyfQ0KbGlua190b29sX3YxPC1yZWFkLmNzdigiY3JzcF9pYmVzX2xpbmsuY3N2IixoZWFkZXIgPSBUUlVFKQ0KbGlua190b29sX3YxPC0gbGlua190b29sX3YxJT4lZmlsdGVyKFNDT1JFIT02KQ0KbGlua190b29sX3RpY2tlciA8LSBzdWJzZXQobGlua190b29sX3YxLCBzZWxlY3QgPSBjKCdUSUNLRVInLCdOQ1VTSVAnLCdQRVJNTk8nKSkNCmBgYA0KQ29tcHUgc3RhdCBwdWxsDQpgYGB7cn0NCnJlcyA8LSBkYlNlbmRRdWVyeSh3cmRzLCAic2VsZWN0IGd2a2V5LCBkYXRhZGF0ZSwgY29ubSxjdXNpcCwgZnlyLCBmeWVhciwgZXhjaGcsIGJrdmxwcywgZXBzZngsIGZpYyBmcm9tIGNvbXAuZnVuZGENCiAgICAgICAgICAgICAgICAgICB3aGVyZQ0KICAgICAgICAgICAgICAgICAgIGZ5ciA9ICcxMicgYW5kIA0KICAgICAgICAgICAgICAgICAgIGV4Y2hnIDw+IDAgYW5kIA0KICAgICAgICAgICAgICAgICAgIGV4Y2hnIDw+IDEgYW5kDQogICAgICAgICAgICAgICAgICAgZXhjaGcgPD4gMTkgYW5kDQogICAgICAgICAgICAgICAgICAgcG9wc3JjID0gJ0QnIGFuZCANCiAgICAgICAgICAgICAgICAgICBjb25zb2wgPSAnQycgYW5kIA0KICAgICAgICAgICAgICAgICAgIGRhdGFmbXQgPSAnU1REJyIpDQpjb21wdXN0YXRfZGF0YSA8LSBkYkZldGNoKHJlcywgbj0tMSkNCmRiQ2xlYXJSZXN1bHQocmVzKQ0KaGVhZChjb21wdXN0YXRfZGF0YSkNCmBgYA0KIyBDbGVhbiBDb21wdXN0YXQgRGF0YQ0KYGBge3J9DQpjb21wdXN0YXRfZGF0YV92MTwtY29tcHVzdGF0X2RhdGENCmNvbXB1c3RhdF9kYXRhX3YxPC0gY29tcHVzdGF0X2RhdGFfdjElPiVkcm9wX25hKGJrdmxwcykNCmBgYA0KIyBHcmFiIHRoZSBTZWN1cml0eSBmaWxlcyBmb3IgY29tcHVzdGF0IGZvciB1cyBmaXJzdA0KYGBge3J9DQpyZXMgPC0gZGJTZW5kUXVlcnkod3JkcywgInNlbGVjdCBndmtleSwgaWJ0aWMgZnJvbSBjb21wLnNlY3VyaXR5IikNCmNvbXB1c3RhdF9zZWN1cml0eV9kYXRhIDwtIGRiRmV0Y2gocmVzLCBuPS0xKQ0KZGJDbGVhclJlc3VsdChyZXMpDQpgYGANCiMgVGFrZSBvdXQgYW55IE5BJ3MgaW4gY29tcHVzdGF0IHNlY3VyaXR5DQpgYGB7cn0NCmNvbXB1c3RhdF9zZWN1cml0eV9kYXRhX3YxPC1jb21wdXN0YXRfc2VjdXJpdHlfZGF0YQ0KY29tcHVzdGF0X3NlY3VyaXR5X2RhdGFfdjE8LSBjb21wdXN0YXRfc2VjdXJpdHlfZGF0YV92MSU+JWRyb3BfbmEoaWJ0aWMpDQpoZWFkKGNvbXB1c3RhdF9zZWN1cml0eV9kYXRhX3YxKQ0KYGBgDQojIEdyYWIgdGhlIFNlY3VyaXR5IGZpbGVzIGZvciBjb21wdXN0YXQgZm9yIGdsb2JhbCBmaXJzdA0KYGBge3J9DQpyZXMgPC0gZGJTZW5kUXVlcnkod3JkcywgInNlbGVjdCBndmtleSwgaWJ0aWMgZnJvbSBjb21wLmdfc2VjdXJpdHkiKQ0KY29tcHVzdGF0X2dsb2JhbF9zZWN1cml0eV9kYXRhIDwtIGRiRmV0Y2gocmVzLCBuPS0xKQ0KZGJDbGVhclJlc3VsdChyZXMpDQpgYGANCiMgVGFrZSBvdXQgYW55IE5BJ3MgaW4gIGdsb2JhbCBjb21wdXN0YXQgc2VjdXJpdHkNCmBgYHtyfQ0KY29tcHVzdGF0X2dsb2JhbF9zZWN1cml0eV9kYXRhX3YxPC1jb21wdXN0YXRfZ2xvYmFsX3NlY3VyaXR5X2RhdGENCmNvbXB1c3RhdF9nbG9iYWxfc2VjdXJpdHlfZGF0YV92MTwtIGNvbXB1c3RhdF9nbG9iYWxfc2VjdXJpdHlfZGF0YV92MSU+JWRyb3BfbmEoaWJ0aWMpDQpoZWFkKGNvbXB1c3RhdF9nbG9iYWxfc2VjdXJpdHlfZGF0YV92MSkNCmBgYA0KIyBNZXJnZSBib3RoIGdsb2JhbCBhbmQgTkEgY29tcHVzdGF0IHRvIGliZXMgbGluaw0KYGBge3J9DQpjb21wdXN0YXRfbGlua190b19JQkVTPC1yYmluZChjb21wdXN0YXRfc2VjdXJpdHlfZGF0YV92MSwgY29tcHVzdGF0X2dsb2JhbF9zZWN1cml0eV9kYXRhX3YxKQ0KaGVhZChjb21wdXN0YXRfbGlua190b19JQkVTKQ0KYGBgDQojIE5vdyBtZXJnZSB0aGlzIHdpdGggdGhlIG9yaWdpbmFsIGNvbXB1c3RhdCBkYXRhIHRvIGhhdmUgdGhlIGxpbmsgdG8gSUJFUw0KYGBge3J9DQpjb21wdXN0YXRfZGF0YV92MjwtIGlubmVyX2pvaW4oY29tcHVzdGF0X2RhdGFfdjEsIGNvbXB1c3RhdF9saW5rX3RvX0lCRVMsIGJ5ID1jKCdndmtleSc9J2d2a2V5JykpDQpjb21wdXN0YXRfZGF0YV92MjwtY29tcHVzdGF0X2RhdGFfdjIlPiVncm91cF9ieShndmtleSkNCmNvbXB1c3RhdF9kYXRhX3YyDQpgYGANCiMgTm93IG9ubHkgaW5jbHVkZSBjb21wYW5pZXMgdGhhdCBhcmUgdHJhY2tlZCBieSBib3RoIElCRVMgYW5kIENSU1AgdXNpbmcgdGhlIGxpbmsgdG9vbA0KYGBge3J9DQpjb21wdXN0YXRfZGF0YV92MyA8LSBpbm5lcl9qb2luKGNvbXB1c3RhdF9kYXRhX3YyLCBsaW5rX3Rvb2xfdGlja2VyLCBieSA9IGMoJ2lidGljJz0nVElDS0VSJykpDQpjb21wdXN0YXRfZGF0YV92Mw0KYGBgDQojIFNhdmUgdGhpcyBkYXRhIHRvIGFuIGV4Y2VsIA0KYGBge3J9DQp3cml0ZS5jc3YoY29tcHVzdGF0X2RhdGFfdjMsImNvbXB1c3RhdF9kYXRhX3ZmLmNzdiIpDQpgYGANCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCklCRVMgcHVsbA0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KUHVsbCBJbnRlcm5hdGlvbmFsIElCRVMgU3VtbWFyeSBEYXRhDQpgYGB7cn0NCnJlcyA8LSBkYlNlbmRRdWVyeSh3cmRzLCAic2VsZWN0IHRpY2tlciwgY3VzaXAsY25hbWUsZmlzY2FscCxzdGF0cGVycyxhY3R1YWwsIGFubmRhdHNfYWN0LCBhY3RkYXRzX2FjdCxudW1lc3QsbWVhbmVzdCwgbWVkZXN0LGZwZWRhdHMsdXNmaXJtLCBmcGkgZnJvbSBpYmVzLk5TVEFUU1VNX0VQU0lOVA0KICAgICAgICAgICAgICAgICAgIHdoZXJlIGZpc2NhbHAgPSAnQU5OJyANCiAgICAgICAgICAgICAgICAgICAiKQ0KaWJlc19pbnRfc3RhdF9zdW1fZGF0YSA8LSBkYkZldGNoKHJlcywgbj0tMSkNCmRiQ2xlYXJSZXN1bHQocmVzKQ0KaGVhZChpYmVzX2ludF9zdGF0X3N1bV9kYXRhKQ0KYGBgDQpQdWxsIFVTIElCRVMgU3VtbWFyeSBEYXRhDQpgYGB7cn0NCnJlcyA8LSBkYlNlbmRRdWVyeSh3cmRzLCAic2VsZWN0IHRpY2tlciwgY3VzaXAsY25hbWUsZmlzY2FscCxzdGF0cGVycyxhY3R1YWwsIGFubmRhdHNfYWN0LCBhY3RkYXRzX2FjdCxudW1lc3QsbWVhbmVzdCwgbWVkZXN0LGZwZWRhdHMsdXNmaXJtLGZwaSBmcm9tIGliZXMuTlNUQVRTVU1fRVBTVXMNCiAgICAgICAgICAgICAgICAgICB3aGVyZSBmaXNjYWxwID0gJ0FOTicgYW5kIA0KICAgICAgICAgICAgICAgICAgIG51bWVzdCA+PTENCiAgICAgICAgICAgICAgICAgICAiKQ0KaWJlc19VU19zdGF0X3N1bV9kYXRhIDwtIGRiRmV0Y2gocmVzLCBuPS0xKQ0KZGJDbGVhclJlc3VsdChyZXMpDQpoZWFkKGliZXNfVVNfc3RhdF9zdW1fZGF0YSkNCmBgYA0KTWVyZ2VyIGJvdGggaWJlcyB0b2dldGhlcg0KYGBge3J9DQpjb21wbGV0ZV9pYmVzX2RhdGE8LXJiaW5kKGliZXNfaW50X3N0YXRfc3VtX2RhdGEsIGliZXNfVVNfc3RhdF9zdW1fZGF0YSkNCmhlYWQoY29tcGxldGVfaWJlc19kYXRhKQ0KYGBgDQpSZW5hbWUgdGhlIGNvbHVtbnMgDQpgYGB7cn0NCmNvbXBsZXRlX2liZXNfZGF0YV92MTwtY29tcGxldGVfaWJlc19kYXRhDQpjb21wbGV0ZV9pYmVzX2RhdGFfdjE8LXJlbmFtZShjb21wbGV0ZV9pYmVzX2RhdGFfdjEsZm9yZWNhc3RfZGF0ZT1zdGF0cGVycywgYWN0dWFsX2Vhcm5pbmdzPWFjdHVhbCwgZm9yZWNhc3RlZF9wZXJpb2Q9ZnBlZGF0cykNCmNvbXBsZXRlX2liZXNfZGF0YV92MTwtY29tcGxldGVfaWJlc19kYXRhX3YxJT4lZ3JvdXBfYnkodGlja2VyKQ0KY29tcGxldGVfaWJlc19kYXRhX3YxDQpgYGANCk9ubHkgZ2V0IGZpc2NhbCB5ZWFyIDEyIGVuZCwgZm9yZWNhc3QgcGVyaW9kIG9mIDEgKEZQSSkgYW5kIHRha2Ugb3V0IG5hcyANCmBgYHtyfQ0KY29tcGxldGVfaWJlc19kYXRhX3YyPC1jb21wbGV0ZV9pYmVzX2RhdGFfdjENCiMgTW9udGggd2hlcmUgdGhlIGFuYWx5c3QgZm9yZWNhc3RlZA0KY29tcGxldGVfaWJlc19kYXRhX3YyJGZpc2NhbF95ZWFyX2VuZF9tb250aCA8LSBmb3JtYXQoY29tcGxldGVfaWJlc19kYXRhX3YyJGZvcmVjYXN0ZWRfcGVyaW9kLCIlbSIpDQpjb21wbGV0ZV9pYmVzX2RhdGFfdjI8LWNvbXBsZXRlX2liZXNfZGF0YV92MiU+JWZpbHRlcihmaXNjYWxfeWVhcl9lbmRfbW9udGg9PTEyKQ0KY29tcGxldGVfaWJlc19kYXRhX3YyPC1jb21wbGV0ZV9pYmVzX2RhdGFfdjIlPiUgZmlsdGVyKGZwaT09MSkNCmNvbXBsZXRlX2liZXNfZGF0YV92MjwtY29tcGxldGVfaWJlc19kYXRhX3YyJT4lIGRyb3BfbmEoYWN0dWFsX2Vhcm5pbmdzKQ0KYGBgDQpGaW5kIHRoZSBsYXJnZXN0IGZvcmVjYXN0IGRhdGUgZm9yIGFueSBnaXZlbiBmb3JlY2FzdCB5ZWFyIA0KYGBge3J9DQpsYXJnZXN0X2ZvcmVjYXN0X2RhdGVfbWF4IDwtIGNvbXBsZXRlX2liZXNfZGF0YV92MiU+JWdyb3VwX2J5KHRpY2tlcixmb3JlY2FzdGVkX3BlcmlvZCklPiVzdW1tYXJpc2UobWF4PW1heChmb3JlY2FzdF9kYXRlKSkNCmxhcmdlc3RfZm9yZWNhc3RfZGF0ZV9taW4gPC0gY29tcGxldGVfaWJlc19kYXRhX3YyJT4lZ3JvdXBfYnkodGlja2VyLGZvcmVjYXN0ZWRfcGVyaW9kKSU+JXN1bW1hcmlzZShtaW49bWluKGZvcmVjYXN0X2RhdGUpKQ0KbGFyZ2VzdF9mb3JlY2FzdF9kYXRlX21heA0KbGFyZ2VzdF9mb3JlY2FzdF9kYXRlX21pbg0KYGBgDQpDcmVhdGUgSUJFUyBjb25zZW5zdXMgZm9yZWNhc3QgZGF0YWJhc2UNCmBgYHtyfQ0KaWJlc19mb3JlY2FzdF9maXJzdF9mb3JlY2FzdDwtaW5uZXJfam9pbihjb21wbGV0ZV9pYmVzX2RhdGFfdjIsbGFyZ2VzdF9mb3JlY2FzdF9kYXRlX21pbixieT1jKCd0aWNrZXInPSd0aWNrZXInLCdmb3JlY2FzdGVkX3BlcmlvZCc9J2ZvcmVjYXN0ZWRfcGVyaW9kJywnZm9yZWNhc3RfZGF0ZSc9J21pbicpKQ0KaWJlc19mb3JlY2FzdF9sYXN0X2ZvcmVjYXN0PC1pbm5lcl9qb2luKGNvbXBsZXRlX2liZXNfZGF0YV92MixsYXJnZXN0X2ZvcmVjYXN0X2RhdGVfbWF4LGJ5PWMoJ3RpY2tlcic9J3RpY2tlcicsJ2ZvcmVjYXN0ZWRfcGVyaW9kJz0nZm9yZWNhc3RlZF9wZXJpb2QnLCdmb3JlY2FzdF9kYXRlJz0nbWF4JykpDQppYmVzX2ZvcmVjYXN0X2ZpcnN0X2ZvcmVjYXN0DQppYmVzX2ZvcmVjYXN0X2xhc3RfZm9yZWNhc3QNCmBgYA0KIyBDb2x1bW4gY29tcGFyaXNvbiBvZiBiZWF0IG9yIGxvc3MNCmBgYHtyfQ0KIyBVc2luZyBNZWFuIEVzdGltYXRlcyBmb3IgdGhlIGZpcnN0IGVhcm5pbmdzIGZvcmVjYXN0IGRhdGUgcmVjb3JkZWQNCmliZXNfZm9yZWNhc3RfZmlyc3RfZm9yZWNhc3QkYWJvdmVfZXhwZWN0YXRpb25zX21lYW48LTANCmliZXNfZm9yZWNhc3RfZmlyc3RfZm9yZWNhc3QkYmVsb3dfZXhwZWN0YXRpb25zX21lYW4gPC0wDQppYmVzX2ZvcmVjYXN0X2ZpcnN0X2ZvcmVjYXN0JGFib3ZlX2V4cGVjdGF0aW9uc19tZWFuW2liZXNfZm9yZWNhc3RfZmlyc3RfZm9yZWNhc3QkYWN0dWFsX2Vhcm5pbmdzPmliZXNfZm9yZWNhc3RfZmlyc3RfZm9yZWNhc3QkbWVhbmVzdF08LTENCmliZXNfZm9yZWNhc3RfZmlyc3RfZm9yZWNhc3QkYmVsb3dfZXhwZWN0YXRpb25zX21lYW5baWJlc19mb3JlY2FzdF9maXJzdF9mb3JlY2FzdCRhYm92ZV9leHBlY3RhdGlvbnNfbWVhbj09MF08LTENCg0KIyBVc2luZyBNZWRpYW4gRXN0aW1hdGVzIGZvciB0aGUgZmlyc3QgZWFybmluZ3MgZm9yZWNhc3QgZGF0ZSByZWNvcmRlZA0KaWJlc19mb3JlY2FzdF9maXJzdF9mb3JlY2FzdCRhYm92ZV9leHBlY3RhdGlvbnNfbWVkaWFuPC0wDQppYmVzX2ZvcmVjYXN0X2ZpcnN0X2ZvcmVjYXN0JGJlbG93X2V4cGVjdGF0aW9uc19tZWRpYW4gPC0wDQppYmVzX2ZvcmVjYXN0X2ZpcnN0X2ZvcmVjYXN0JGFib3ZlX2V4cGVjdGF0aW9uc19tZWRpYW5baWJlc19mb3JlY2FzdF9maXJzdF9mb3JlY2FzdCRhY3R1YWxfZWFybmluZ3M+aWJlc19mb3JlY2FzdF9maXJzdF9mb3JlY2FzdCRtZWRlc3RdPC0xDQppYmVzX2ZvcmVjYXN0X2ZpcnN0X2ZvcmVjYXN0JGJlbG93X2V4cGVjdGF0aW9uc19tZWRpYW5baWJlc19mb3JlY2FzdF9maXJzdF9mb3JlY2FzdCRhYm92ZV9leHBlY3RhdGlvbnNfbWVkaWFuPT0wXTwtMQ0KDQojIFVzaW5nIE1lYW4gRXN0aW1hdGVzIGZvciB0aGUgbGFzdCBlYXJuaW5ncyBmb3JlY2FzdCBkYXRlIHJlY29yZGVkDQppYmVzX2ZvcmVjYXN0X2xhc3RfZm9yZWNhc3QkYWJvdmVfZXhwZWN0YXRpb25zX21lYW48LTANCmliZXNfZm9yZWNhc3RfbGFzdF9mb3JlY2FzdCRiZWxvd19leHBlY3RhdGlvbnNfbWVhbiA8LTANCmliZXNfZm9yZWNhc3RfbGFzdF9mb3JlY2FzdCRhYm92ZV9leHBlY3RhdGlvbnNfbWVhbltpYmVzX2ZvcmVjYXN0X2xhc3RfZm9yZWNhc3QkYWN0dWFsX2Vhcm5pbmdzPmliZXNfZm9yZWNhc3RfbGFzdF9mb3JlY2FzdCRtZWFuZXN0XTwtMQ0KaWJlc19mb3JlY2FzdF9sYXN0X2ZvcmVjYXN0JGJlbG93X2V4cGVjdGF0aW9uc19tZWFuW2liZXNfZm9yZWNhc3RfbGFzdF9mb3JlY2FzdCRhYm92ZV9leHBlY3RhdGlvbnNfbWVhbj09MF08LTENCg0KIyBVc2luZyBNZWRpYW4gRXN0aW1hdGVzIGZvciB0aGUgbGFzdCBlYXJuaW5ncyBmb3JlY2FzdCBkYXRlIHJlY29yZGVkDQppYmVzX2ZvcmVjYXN0X2xhc3RfZm9yZWNhc3QkYWJvdmVfZXhwZWN0YXRpb25zX21lZGlhbjwtMA0KaWJlc19mb3JlY2FzdF9sYXN0X2ZvcmVjYXN0JGJlbG93X2V4cGVjdGF0aW9uc19tZWRpYW4gPC0wDQppYmVzX2ZvcmVjYXN0X2xhc3RfZm9yZWNhc3QkYWJvdmVfZXhwZWN0YXRpb25zX21lZGlhbltpYmVzX2ZvcmVjYXN0X2xhc3RfZm9yZWNhc3QkYWN0dWFsX2Vhcm5pbmdzPmliZXNfZm9yZWNhc3RfbGFzdF9mb3JlY2FzdCRtZWRlc3RdPC0xDQppYmVzX2ZvcmVjYXN0X2xhc3RfZm9yZWNhc3QkYmVsb3dfZXhwZWN0YXRpb25zX21lZGlhbltpYmVzX2ZvcmVjYXN0X2xhc3RfZm9yZWNhc3QkYWJvdmVfZXhwZWN0YXRpb25zX21lZGlhbj09MF08LTENCg0KaWJlc19mb3JlY2FzdF9maXJzdF9mb3JlY2FzdA0KaWJlc19mb3JlY2FzdF9sYXN0X2ZvcmVjYXN0DQpgYGANCiMgTm93IHdlIG11c3QgbGluayBiYWNrIHRvIHRoZSB0aWNrZXIgc2V0IHdlIGFyZSB1c2luZw0KYGBge3J9DQppYmVzX2ZvcmVjYXN0X2ZpcnN0X2ZvcmVjYXN0X2xpbmtlZDwtaW5uZXJfam9pbihpYmVzX2ZvcmVjYXN0X2ZpcnN0X2ZvcmVjYXN0LGxpbmtfdG9vbF90aWNrZXIsIGJ5ID0gYygndGlja2VyJz0nVElDS0VSJykpDQppYmVzX2ZvcmVjYXN0X2xhc3RfZm9yZWNhc3RfbGlua2VkPC1pbm5lcl9qb2luKGliZXNfZm9yZWNhc3RfbGFzdF9mb3JlY2FzdCxsaW5rX3Rvb2xfdGlja2VyLCBieSA9IGMoJ3RpY2tlcic9J1RJQ0tFUicpKQ0KaWJlc19mb3JlY2FzdF9maXJzdF9mb3JlY2FzdF9saW5rZWQNCmliZXNfZm9yZWNhc3RfbGFzdF9mb3JlY2FzdF9saW5rZWQNCmBgYA0KIyBTYXZlIHRoZXNlIElCRVMgZm9yZWNhc3RzIA0KYGBge3J9DQp3cml0ZS5jc3YoaWJlc19mb3JlY2FzdF9maXJzdF9mb3JlY2FzdF9saW5rZWQsImliZXNfZm9yZWNhc3RfZmlyc3RfZm9yZWNhc3RfbGlua2VkLmNzdiIpDQp3cml0ZS5jc3YoaWJlc19mb3JlY2FzdF9sYXN0X2ZvcmVjYXN0X2xpbmtlZCwiaWJlc19mb3JlY2FzdF9sYXN0X2ZvcmVjYXN0X2xpbmtlZC5jc3YiKQ0KYGBgDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQpDUlNQIGRhdGENCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCmBgYHtyfQ0KIyBoZXhjZCAxID0gTllTRSwgaGV4Y2QgMiA9IEFNRVgsIGhleGNkIDMgPSBOQVNEQVEgDQpyZXMgPC0gZGJTZW5kUXVlcnkod3JkcywgInNlbGVjdCBkYXRlLHBlcm1ubyxjdXNpcCxwcmMsIHJldCwgdm9sLCBzaHJvdXQgLGhleGNkLCBjZmFjcHIgZnJvbSBjcnNwYS5tc2YNCiAgICAgICAgICAgICAgICAgICB3aGVyZSBwcmMgPjAiKQ0KY3JzcF9kYXRhIDwtIGRiRmV0Y2gocmVzLCBuPS0xKQ0KZGJDbGVhclJlc3VsdChyZXMpDQpgYGANCiMgQWRqdXN0IHRoZSBwcmljZSBhbmQgb21pdCBuYXMNCmBgYHtyfQ0KY29sX29yZGVyIDwtIGMoImRhdGUiLCJ5ZWFyIiwgIm1vbnRoIiwgInBlcm1ubyIsImN1c2lwIiwgInByaWNlIiwibW9udGhseV9yZXR1cm5zIiwidm9sdW1lIiwic2hhcmVzX291dHN0YW5kaW5nIiwibWFya2V0X2NhcGl0YWxpemF0aW9uIiwiZXhjaGFuZ2UiKQ0KIyBPbWl0IGFsbCByb3dzIHdpdGggaW5jb21wbGV0ZSBkYXRhDQpjcnNwX2RhdGFfdjE8LWNyc3BfZGF0YSU+JWRyb3BfbmEoY2ZhY3ByLHZvbCxwcmMsc2hyb3V0LHJldCkNCiMgQWRqdXN0IFByaWNlIGJ5IHByaWNlIGFkanVzdG1lbnQgZmFjdG9yIA0KY3JzcF9kYXRhX3YxJHByYyA8LSBhYnMoY3JzcF9kYXRhX3YxJHByYykvY3JzcF9kYXRhX3YxJGNmYWNwcg0KaGVhZChjcnNwX2RhdGFfdjEpDQpgYGANCiMgTWF0Y2ggdGhpcyB0byBjcnNwIGxpbmsNCmBgYHtyfQ0KY3JzcF9kYXRhX3YyPC0gaW5uZXJfam9pbihjcnNwX2RhdGFfdjEsIGxpbmtfdG9vbF90aWNrZXIsYnk9YygncGVybW5vJz0nUEVSTU5PJykpDQpoZWFkKGNyc3BfZGF0YV92MikNCmBgYA0KIyBHZXQgcHJpY2UgYXMgb2YgdGhlIGxhc3QgZGF5IG9mIGFwcmlsIA0KYGBge3J9DQpjcnNwX2RhdGFfdjM8LWNyc3BfZGF0YV92Mg0KY3JzcF9kYXRhX3YzJHByaWNlX21vbnRoIDwtIGZvcm1hdChjcnNwX2RhdGFfdjMkZGF0ZSwiJW0iKQ0KY3JzcF9kYXRhX3YzPC1jcnNwX2RhdGFfdjMlPiVmaWx0ZXIocHJpY2VfbW9udGg9PScwNCcpDQpoZWFkKGNyc3BfZGF0YV92MykNCmBgYA0KIyBTY3JlZW4gdG8gb25seSBnZXQgb25lIGVudHJ5IHBlciBwZXJtbm8gcGVyIGRhdGUgDQpgYGB7cn0NCmNyc3BfZGF0YV92NDwtY3JzcF9kYXRhX3YzDQpjcnNwX2RhdGFfdjQ8LWNyc3BfZGF0YV92NCU+JWRpc3RpbmN0KHBlcm1ubyxkYXRlLC5rZWVwX2FsbCA9IFRSVUUpDQpjcnNwX2RhdGFfdjQ8LWNyc3BfZGF0YV92NCU+JWdyb3VwX2J5KHBlcm1ubykNCmNyc3BfZGF0YV92NA0KYGBgDQojIHNhdmUgdGhpcyBjc3YNCmBgYHtyfQ0Kd3JpdGUuY3N2KGNyc3BfZGF0YV92NCwgImNyc3BfZGF0YV92Zi5jc3YiKQ0KYGBgDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQpOb3cgd2Ugd2FudCB0byBtZXJnZSB0aGUgdGhyZWUgZGF0YWJhc2VzIHRvIGZvcm0gb3VyIHF1YXJ0aWxlcw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KYGBge3J9DQpjb21wdXN0YXRfZGF0YTwtcmVhZC5jc3YoImNvbXB1c3RhdF9kYXRhX3ZmLmNzdiIsaGVhZGVyID0gVFJVRSkNCmNyc3BfZGF0YTwtcmVhZC5jc3YoImNyc3BfZGF0YV92Zi5jc3YiLGhlYWRlciA9IFRSVUUpDQpJQkVTX2RhdGE8LXJlYWQuY3N2KCJpYmVzX2ZvcmVjYXN0X2xhc3RfZm9yZWNhc3RfbGlua2VkLmNzdiIsIGhlYWRlcj1UUlVFKQ0KY29tcHVzdGF0X2RhdGE8LWNvbXB1c3RhdF9kYXRhJT4lZ3JvdXBfYnkoZ3ZrZXkpDQpjcnNwX2RhdGE8LWNyc3BfZGF0YSU+JWdyb3VwX2J5KHBlcm1ubykNCklCRVNfZGF0YTwtSUJFU19kYXRhJT4lZ3JvdXBfYnkodGlja2VyKQ0KY29tcHVzdGF0X2RhdGENCmNyc3BfZGF0YQ0KSUJFU19kYXRhDQpgYGANCiMgR2V0IG9ubHkgdGhlIGNvbHVtbnMgd2Ugd2FudCBmcm9tIGVhY2ggdGFibGUgDQpgYGB7cn0NCiMgVGFrZSB0aGUgY29sdW1zbiB3ZSBuZWVkDQpjb2x1bW5zPC1jKCdmeWVhcicsJ2lidGljJywnTkNVU0lQJywnUEVSTU5PJywnYmt2bHBzJywnZXBzZngnKQ0KbW9kaWZpZWRfY29tcHVzdGF0X2RhdGE8LWNvbXB1c3RhdF9kYXRhWyxjb2x1bW5zXQ0KY29sdW1uczwtYygnZGF0ZScsJ3Blcm1ubycsJ3ByYycsJ1RJQ0tFUicpDQptb2RpZmllZF9jcnNwX2RhdGE8LWNyc3BfZGF0YVssY29sdW1uc10NCmNvbHVtbnM8LWMoJ3RpY2tlcicsJ1BFUk1OTycsJ2NuYW1lJywnZm9yZWNhc3RfZGF0ZScsJ2FjdHVhbF9lYXJuaW5ncycsJ2ZvcmVjYXN0ZWRfcGVyaW9kJywnYWJvdmVfZXhwZWN0YXRpb25zX21lYW4nLCdhYm92ZV9leHBlY3RhdGlvbnNfbWVkaWFuJywnYmVsb3dfZXhwZWN0YXRpb25zX21lYW4nLCdiZWxvd19leHBlY3RhdGlvbnNfbWVkaWFuJywnbnVtZXN0JykNCm1vZGlmaWVkX2liZXNfZGF0YTwtSUJFU19kYXRhWyxjb2x1bW5zXQ0KbW9kaWZpZWRfY29tcHVzdGF0X2RhdGENCm1vZGlmaWVkX2Nyc3BfZGF0YQ0KbW9kaWZpZWRfaWJlc19kYXRhDQpgYGANCiMgR2V0IHRoZSBmaXNjbCB5ZWFyIHByaW9yIA0KYGBge3J9DQptb2RpZmllZF9jcnNwX2RhdGEkZGF0ZTwtYXMuRGF0ZShtb2RpZmllZF9jcnNwX2RhdGEkZGF0ZSkNCm1vZGlmaWVkX2Nyc3BfZGF0YSR5ZWFyPC0gZm9ybWF0KG1vZGlmaWVkX2Nyc3BfZGF0YSRkYXRlLCIlWSIpDQptb2RpZmllZF9jcnNwX2RhdGEkeWVhcjwtYXMubnVtZXJpYyhtb2RpZmllZF9jcnNwX2RhdGEkeWVhcikNCm1vZGlmaWVkX2Nyc3BfZGF0YSRwcmV2aW91c195ZWFyPC1tb2RpZmllZF9jcnNwX2RhdGEkeWVhci0xDQpjb2x1bW5zPC1jKCdwZXJtbm8nLCdUSUNLRVInLCdkYXRlJywncHJjJywgJ3ByZXZpb3VzX3llYXInKQ0KbW9kaWZpZWRfY3JzcF9kYXRhPC1tb2RpZmllZF9jcnNwX2RhdGFbLGNvbHVtbnNdDQptb2RpZmllZF9jcnNwX2RhdGENCmBgYA0KIyBNZXJnZSBDcnNwIGFuZCBDb21wdXN0YXQNCmBgYHtyfQ0KbWVyZ2VkX2Nyc3BfY29tcHVzdGF0PC1pbm5lcl9qb2luKG1vZGlmaWVkX2NvbXB1c3RhdF9kYXRhLG1vZGlmaWVkX2Nyc3BfZGF0YSxieT1jKCdQRVJNTk8nPSdwZXJtbm8nLCAnaWJ0aWMnPSdUSUNLRVInLCdmeWVhcic9J3ByZXZpb3VzX3llYXInKSkNCm1lcmdlZF9jcnNwX2NvbXB1c3RhdDwtbWVyZ2VkX2Nyc3BfY29tcHVzdGF0JT4lZHJvcF9uYShlcHNmeCkNCm1lcmdlZF9jcnNwX2NvbXB1c3RhdCRQRV9SYXRpbzwtbWVyZ2VkX2Nyc3BfY29tcHVzdGF0JHByYy9tZXJnZWRfY3JzcF9jb21wdXN0YXQkZXBzZngNCm1lcmdlZF9jcnNwX2NvbXB1c3RhdCRQQl9SYXRpbzwtbWVyZ2VkX2Nyc3BfY29tcHVzdGF0JHByYy9tZXJnZWRfY3JzcF9jb21wdXN0YXQkYmt2bHBzDQptZXJnZWRfY3JzcF9jb21wdXN0YXQNCmBgYA0KIyBRdWFydGlsZSB0aGUgZGF0YSBvbiBQQiBhbmQgUEUNCmBgYHtyfQ0KbWVyZ2VkX2Nyc3BfY29tcHVzdGF0PC1tZXJnZWRfY3JzcF9jb21wdXN0YXQlPiVncm91cF9ieShmeWVhciklPiVtdXRhdGUocXVhcnRpbGVfUEVfcmF0aW89bnRpbGUoUEVfUmF0aW8sNCkpDQptZXJnZWRfY3JzcF9jb21wdXN0YXQ8LW1lcmdlZF9jcnNwX2NvbXB1c3RhdCU+JWdyb3VwX2J5KGZ5ZWFyKSU+JW11dGF0ZShxdWFydGlsZV9QQl9yYXRpbz1udGlsZShQQl9SYXRpbyw0KSkNCiMgVGFrZSBvbmx5IHRoZSB0b3AgYW5kIGJvdHRvbSBxdWFydGlsZXMNCm1lcmdlZF9jcnNwX2NvbXB1c3RhdDwtbWVyZ2VkX2Nyc3BfY29tcHVzdGF0JT4lZmlsdGVyKHF1YXJ0aWxlX1BFX3JhdGlvPT00fHF1YXJ0aWxlX1BFX3JhdGlvPT0xfHF1YXJ0aWxlX1BCX3JhdGlvPT00fHF1YXJ0aWxlX1BCX3JhdGlvPT0xKQ0KIyBTZXQgdXAgZHVtbWllcyBpZiBQcmljZSB0byBib29rIHZhbHVlIA0KbWVyZ2VkX2Nyc3BfY29tcHVzdGF0JHZhbHVlX3N0b2NrX1BCPC0wDQptZXJnZWRfY3JzcF9jb21wdXN0YXQkdmFsdWVfc3RvY2tfUEJbbWVyZ2VkX2Nyc3BfY29tcHVzdGF0JHF1YXJ0aWxlX1BCX3JhdGlvPT0xXTwtMQ0KIyBTZXQgdXAgZHVtbWllcyBpZiBQcmljZSB0byBFYXJuaW5ncyB2YWx1ZSANCm1lcmdlZF9jcnNwX2NvbXB1c3RhdCR2YWx1ZV9zdG9ja19QRTwtMA0KbWVyZ2VkX2Nyc3BfY29tcHVzdGF0JHZhbHVlX3N0b2NrX1BFW21lcmdlZF9jcnNwX2NvbXB1c3RhdCRxdWFydGlsZV9QRV9yYXRpbz09MV08LTENCiMgU2V0IHVwIGR1bW1pZXMgaWYgUHJpY2UgdG8gYm9vayB2YWx1ZSANCm1lcmdlZF9jcnNwX2NvbXB1c3RhdCRncm93dGhfc3RvY2tfUEI8LTENCm1lcmdlZF9jcnNwX2NvbXB1c3RhdCRncm93dGhfc3RvY2tfUEJbbWVyZ2VkX2Nyc3BfY29tcHVzdGF0JHZhbHVlX3N0b2NrX1BCPT0xXTwtMA0KIyBTZXQgdXAgZHVtbWllcyBpZiBQcmljZSB0byBib29rIHZhbHVlIA0KbWVyZ2VkX2Nyc3BfY29tcHVzdGF0JGdyb3d0aF9zdG9ja19QRTwtMQ0KbWVyZ2VkX2Nyc3BfY29tcHVzdGF0JGdyb3d0aF9zdG9ja19QRVttZXJnZWRfY3JzcF9jb21wdXN0YXQkdmFsdWVfc3RvY2tfUEU9PTFdPC0wDQptZXJnZWRfY3JzcF9jb21wdXN0YXQNCmBgYA0KIyBUYWtlIHRoZSBjb2x1bW5zIHdlIG5lZWQgdG8gcHJlcCBmb3IgbWVyZ2UgdG8gaWJlcw0KYGBge3J9DQojIEdldCB0aGUgY29sdW1ucyB3ZSBuZWVkDQpjb2x1bW5zPC1jKCdpYnRpYycsJ1BFUk1OTycsJ2Z5ZWFyJywnZGF0ZScsJ3ZhbHVlX3N0b2NrX1BCJywndmFsdWVfc3RvY2tfUEUnLCdncm93dGhfc3RvY2tfUEInLCdncm93dGhfc3RvY2tfUEUnKQ0KbWVyZ2VkX2Nyc3BfY29tcHVzdGF0X21vZGlmaWVkPC1tZXJnZWRfY3JzcF9jb21wdXN0YXRbLGNvbHVtbnNdDQptZXJnZWRfY3JzcF9jb21wdXN0YXRfbW9kaWZpZWQNCiMgUHJlcCBJQkVTIHRvIGdldCBvdXQgZmlzY2FsIHllYXIgcHJlZGljdGlvbg0KbW9kaWZpZWRfaWJlc19kYXRhJGZvcmVjYXN0ZWRfcGVyaW9kPC1hcy5EYXRlKG1vZGlmaWVkX2liZXNfZGF0YSRmb3JlY2FzdGVkX3BlcmlvZCkNCm1vZGlmaWVkX2liZXNfZGF0YSR5ZWFyPC0gZm9ybWF0KG1vZGlmaWVkX2liZXNfZGF0YSRmb3JlY2FzdGVkX3BlcmlvZCwiJVkiKQ0KY29sdW1uczwtYygndGlja2VyJywnUEVSTU5PJywneWVhcicsJ2NuYW1lJywnYWJvdmVfZXhwZWN0YXRpb25zX21lYW4nLCdhYm92ZV9leHBlY3RhdGlvbnNfbWVkaWFuJywnYmVsb3dfZXhwZWN0YXRpb25zX21lYW4nLCdiZWxvd19leHBlY3RhdGlvbnNfbWVkaWFuJywnbnVtZXN0JykNCm1vZGlmaWVkX2liZXNfZGF0YTwtbW9kaWZpZWRfaWJlc19kYXRhWyxjb2x1bW5zXQ0KbW9kaWZpZWRfaWJlc19kYXRhDQpgYGANCiMgTWVyZ2UgdG8gaWJlcw0KYGBge3J9DQojIENvdmVydCBjaGFyIHRvIG51bWVyaWMNCm1vZGlmaWVkX2liZXNfZGF0YSR5ZWFyPC1hcy5udW1lcmljKG1vZGlmaWVkX2liZXNfZGF0YSR5ZWFyKQ0KY29uc29saWRhdGVkX2Nyc3BfY29tcHVzdGF0X2liZXM8LWlubmVyX2pvaW4obWVyZ2VkX2Nyc3BfY29tcHVzdGF0X21vZGlmaWVkLG1vZGlmaWVkX2liZXNfZGF0YSwgYnkgPSBjKCdmeWVhcic9J3llYXInLCdpYnRpYyc9J3RpY2tlcicsJ1BFUk1OTyc9J1BFUk1OTycpKQ0KY29uc29saWRhdGVkX2Nyc3BfY29tcHVzdGF0X2liZXM8LWNvbnNvbGlkYXRlZF9jcnNwX2NvbXB1c3RhdF9pYmVzJT4lZGlzdGluY3QoaWJ0aWMsUEVSTU5PLGZ5ZWFyLGRhdGUsLmtlZXBfYWxsPVRSVUUpDQpjb25zb2xpZGF0ZWRfY3JzcF9jb21wdXN0YXRfaWJlcw0KYGBgDQojIE9yZ2FuaXplIGFuZCBjbGVhbiB0aGUgZGF0YWJhc2UNCmBgYHtyfQ0KY29sdW1uczwtYygnaWJ0aWMnLCdQRVJNTk8nLCdjbmFtZScsJ2Z5ZWFyJywnZGF0ZScsJ3ZhbHVlX3N0b2NrX1BCJywndmFsdWVfc3RvY2tfUEUnLCdncm93dGhfc3RvY2tfUEInLCdncm93dGhfc3RvY2tfUEUnLCdhYm92ZV9leHBlY3RhdGlvbnNfbWVkaWFuJywnYmVsb3dfZXhwZWN0YXRpb25zX21lYW4nLCdiZWxvd19leHBlY3RhdGlvbnNfbWVkaWFuJykNCmNvbnNvbGlkYXRlZF9jcnNwX2NvbXB1c3RhdF9pYmVzX3ZmPC1jb25zb2xpZGF0ZWRfY3JzcF9jb21wdXN0YXRfaWJlcw0KY29uc29saWRhdGVkX2Nyc3BfY29tcHVzdGF0X2liZXNfdmY8LWNvbnNvbGlkYXRlZF9jcnNwX2NvbXB1c3RhdF9pYmVzX3ZmWyxjb2x1bW5zXQ0KY29uc29saWRhdGVkX2Nyc3BfY29tcHVzdGF0X2liZXNfdmY8LXJlbmFtZShjb25zb2xpZGF0ZWRfY3JzcF9jb21wdXN0YXRfaWJlc192ZixJQkVTX1RpY2tlcl9JRD1pYnRpYywgQ1JTUF9QZXJtbm9fSUQ9UEVSTU5PLEZpc2NhbF9ZZWFyPWZ5ZWFyLFN0b2NrX1ByaWNlX0RhdGU9ZGF0ZSxDb21wYW55X05hbWU9Y25hbWUpDQpjb25zb2xpZGF0ZWRfY3JzcF9jb21wdXN0YXRfaWJlc192Zg0KYGBgDQojIFNhdmUgdGhlIGNvbnNvbGlkYXRlIGRhdGENCmBgYHtyfQ0Kd3JpdGUuY3N2KGNvbnNvbGlkYXRlZF9jcnNwX2NvbXB1c3RhdF9pYmVzX3ZmLCJjb25zb2xpZGF0ZWRfY3JzcF9jb21wdXN0YXRfaWJlc192Zi5jc3YiKQ0KYGBgDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQpOb3cgd2Ugd2FudCB0byBnZXQgOTAgZGF5IHJldHVybiBhbmQgdGhlbiBvbmUgeWVhciByZXR1cm4gb24gdGhlIHN0b2NrIA0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KYGBge3J9DQpjb2x1bW5zPC1jKCdJQkVTX1RpY2tlcl9JRCcsJ0NSU1BfUGVybW5vX0lEJywnQ29tcGFueV9OYW1lJywnRmlzY2FsX1llYXInLCdTdG9ja19QcmljZV9EYXRlJykNCmZvcndhcmRfZGF0ZXM8LWNvbnNvbGlkYXRlZF9jcnNwX2NvbXB1c3RhdF9pYmVzX3ZmWyxjb2x1bW5zXQ0KZm9yd2FyZF9kYXRlcyRkYXRlX2FkZF85MDwtZm9yd2FyZF9kYXRlcyRTdG9ja19QcmljZV9EYXRlKzkwDQpmb3J3YXJkX2RhdGVzJGRhdGVfYWRkX29uZV95ZWFyPC1mb3J3YXJkX2RhdGVzJFN0b2NrX1ByaWNlX0RhdGUrMzY1DQpmb3J3YXJkX2RhdGVzJHF1YXJ0ZXJfbW9udGg8LWZvcm1hdChmb3J3YXJkX2RhdGVzJGRhdGVfYWRkXzkwLCIlbSIpDQpmb3J3YXJkX2RhdGVzJHF1YXJ0ZXJfeWVhcjwtZm9ybWF0KGZvcndhcmRfZGF0ZXMkZGF0ZV9hZGRfOTAsIiVZIikNCmZvcndhcmRfZGF0ZXMkZnV0dXJlX21vbnRoPC1mb3JtYXQoZm9yd2FyZF9kYXRlcyRkYXRlX2FkZF9vbmVfeWVhciwiJW0iKQ0KZm9yd2FyZF9kYXRlcyRmdXR1cmVfeWVhcjwtZm9ybWF0KGZvcndhcmRfZGF0ZXMkZGF0ZV9hZGRfb25lX3llYXIsIiVZIikNCmZvcndhcmRfZGF0ZXMNCmBgYA0KI0dldCB0aGUgY3JzcCBwcmljZSBkYXRhIGFnYWluIA0KYGBge3J9DQojIGhleGNkIDEgPSBOWVNFLCBoZXhjZCAyID0gQU1FWCwgaGV4Y2QgMyA9IE5BU0RBUSANCnJlcyA8LSBkYlNlbmRRdWVyeSh3cmRzLCAic2VsZWN0IGRhdGUscGVybW5vLHByYywgY2ZhY3ByIGZyb20gY3JzcGEubXNmDQogICAgICAgICAgICAgICAgICAgd2hlcmUgcHJjID4wIikNCmNyc3BfcHJpY2VfZGF0YSA8LSBkYkZldGNoKHJlcywgbj0tMSkNCmRiQ2xlYXJSZXN1bHQocmVzKQ0KaGVhZChjcnNwX3ByaWNlX2RhdGEpDQpgYGANCiMgTm93IHdlIG9ubHkgd25hdCB0byBrZWVwIHByaWNlIHRoYXQgYXJlIHJlbGV2YW50IA0KYGBge3J9DQpjcnNwX3ByaWNlX2RhdGFfdjE8LWNyc3BfcHJpY2VfZGF0YQ0KY3JzcF9wcmljZV9kYXRhX3YxPC1jcnNwX3ByaWNlX2RhdGFfdjElPiVncm91cF9ieShwZXJtbm8pDQpjcnNwX3ByaWNlX2RhdGFfdjE8LWNyc3BfcHJpY2VfZGF0YV92MSU+JWRyb3BfbmEocHJjKQ0KIyBNb2RpZnkgdGhlIHByaWNlDQpjcnNwX3ByaWNlX2RhdGFfdjEkcHJjIDwtIGFicyhjcnNwX3ByaWNlX2RhdGFfdjEkcHJjKS9jcnNwX3ByaWNlX2RhdGFfdjEkY2ZhY3ByDQojIEJyZWFrIG91dCB0aGUgZGF0ZSANCmNyc3BfcHJpY2VfZGF0YV92MSRtb250aDwtZm9ybWF0KGNyc3BfcHJpY2VfZGF0YV92MSRkYXRlLCIlbSIpDQpjcnNwX3ByaWNlX2RhdGFfdjEkeWVhcjwtZm9ybWF0KGNyc3BfcHJpY2VfZGF0YV92MSRkYXRlLCIlWSIpDQpjcnNwX3ByaWNlX2RhdGFfdjENCmBgYA0KIyBDbGVhbiB1cCBib3RoIHNldHMNCmBgYHtyfQ0KIyBDbGVhbiB1cCBwdWxsZWQgY3JzcCBkYXRhDQpjb2x1bW5zPC1jKCdkYXRlJywncGVybW5vJywncHJjJywnbW9udGgnLCd5ZWFyJykNCmNyc3BfcHJpY2VfZGF0YV92MjwtY3JzcF9wcmljZV9kYXRhX3YxWyxjb2x1bW5zXQ0KIyBQYXJ0aXRpb24gZm9yd2FyZCBkYXRlcyB0YWJsZQ0KY29sdW1uczwtYygnQ1JTUF9QZXJtbm9fSUQnLCdTdG9ja19QcmljZV9EYXRlJywncXVhcnRlcl9tb250aCcsJ3F1YXJ0ZXJfeWVhcicsJ2Z1dHVyZV9tb250aCcsJ2Z1dHVyZV95ZWFyJykNCmZvcndhcmRfZGF0ZXNfdjI8LWZvcndhcmRfZGF0ZXNbLGNvbHVtbnNdDQpjcnNwX3ByaWNlX2RhdGFfdjINCmZvcndhcmRfZGF0ZXNfdjINCmBgYA0KIyBKb2luIHRvIGdldCBmdWxsIGRhdGEgDQpgYGB7cn0NCm9yaWdpbmFsX3NlY3VyaXR5X3ByaWNlPC1pbm5lcl9qb2luKGZvcndhcmRfZGF0ZXNfdjIsY3JzcF9wcmljZV9kYXRhX3YyLGJ5PWMoJ0NSU1BfUGVybW5vX0lEJz0ncGVybW5vJywnU3RvY2tfUHJpY2VfRGF0ZSc9J2RhdGUnKSkNCmNvbHVtbnM8LWMoJ0NSU1BfUGVybW5vX0lEJywnU3RvY2tfUHJpY2VfRGF0ZScsJ3ByYycpDQpvcmlnaW5hbF9zZWN1cml0eV9wcmljZTwtb3JpZ2luYWxfc2VjdXJpdHlfcHJpY2VbLGNvbHVtbnNdDQoNCmZ1dHVyZV9xdWFydGVyX3NlY3VyaXR5X3ByaWNlPC1pbm5lcl9qb2luKGZvcndhcmRfZGF0ZXNfdjIsY3JzcF9wcmljZV9kYXRhX3YyLGJ5PWMoJ0NSU1BfUGVybW5vX0lEJz0ncGVybW5vJywncXVhcnRlcl9tb250aCc9J21vbnRoJywncXVhcnRlcl95ZWFyJz0neWVhcicpKQ0KY29sdW1uczwtYygnQ1JTUF9QZXJtbm9fSUQnLCdTdG9ja19QcmljZV9EYXRlJywncHJjJykNCmZ1dHVyZV9xdWFydGVyX3NlY3VyaXR5X3ByaWNlPC1mdXR1cmVfcXVhcnRlcl9zZWN1cml0eV9wcmljZVssY29sdW1uc10NCmZ1dHVyZV9xdWFydGVyX3NlY3VyaXR5X3ByaWNlPC1yZW5hbWUoZnV0dXJlX3F1YXJ0ZXJfc2VjdXJpdHlfcHJpY2UscXVhcnRlcl9hZnRlcl9wcmljZT1wcmMpDQoNCmZ1dHVyZV95ZWFyX3NlY3VyaXR5X3ByaWNlPC1pbm5lcl9qb2luKGZvcndhcmRfZGF0ZXNfdjIsY3JzcF9wcmljZV9kYXRhX3YyLGJ5PWMoJ0NSU1BfUGVybW5vX0lEJz0ncGVybW5vJywnZnV0dXJlX21vbnRoJz0nbW9udGgnLCdmdXR1cmVfeWVhcic9J3llYXInKSkNCmNvbHVtbnM8LWMoJ0NSU1BfUGVybW5vX0lEJywnU3RvY2tfUHJpY2VfRGF0ZScsJ3ByYycpDQpmdXR1cmVfeWVhcl9zZWN1cml0eV9wcmljZTwtZnV0dXJlX3llYXJfc2VjdXJpdHlfcHJpY2VbLGNvbHVtbnNdDQpmdXR1cmVfeWVhcl9zZWN1cml0eV9wcmljZTwtcmVuYW1lKGZ1dHVyZV95ZWFyX3NlY3VyaXR5X3ByaWNlLHllYXJfYWZ0ZXJfcHJpY2U9cHJjKQ0KDQpvcmlnaW5hbF9zZWN1cml0eV9wcmljZQ0KZnV0dXJlX3F1YXJ0ZXJfc2VjdXJpdHlfcHJpY2UNCmZ1dHVyZV95ZWFyX3NlY3VyaXR5X3ByaWNlDQpgYGANCiMgSm9pbiB0byBnZXQgYWxsIG9mIHRoZXNlIHByaWNlIGRhdGEgdG9nZXRoZXINCmBgYHtyfQ0KY29uc29saWRhdGVkX3ByaWNpbmdfZGF0YTwtaW5uZXJfam9pbihvcmlnaW5hbF9zZWN1cml0eV9wcmljZSwgZnV0dXJlX3F1YXJ0ZXJfc2VjdXJpdHlfcHJpY2UsYnk9YygnQ1JTUF9QZXJtbm9fSUQnPSdDUlNQX1Blcm1ub19JRCcsJ1N0b2NrX1ByaWNlX0RhdGUnPSdTdG9ja19QcmljZV9EYXRlJykpDQpjb25zb2xpZGF0ZWRfcHJpY2luZ19kYXRhPC1pbm5lcl9qb2luKGNvbnNvbGlkYXRlZF9wcmljaW5nX2RhdGEsIGZ1dHVyZV95ZWFyX3NlY3VyaXR5X3ByaWNlLGJ5PWMoJ0NSU1BfUGVybW5vX0lEJz0nQ1JTUF9QZXJtbm9fSUQnLCdTdG9ja19QcmljZV9EYXRlJz0nU3RvY2tfUHJpY2VfRGF0ZScpKQ0KY29uc29saWRhdGVkX3ByaWNpbmdfZGF0YSRxdWFydGVyX2FmdGVyX3JldHVybjwtY29uc29saWRhdGVkX3ByaWNpbmdfZGF0YSRxdWFydGVyX2FmdGVyX3ByaWNlL2NvbnNvbGlkYXRlZF9wcmljaW5nX2RhdGEkcHJjLTENCmNvbnNvbGlkYXRlZF9wcmljaW5nX2RhdGEkYW5udWFsX2FmdGVyX3JldHVybjwtY29uc29saWRhdGVkX3ByaWNpbmdfZGF0YSR5ZWFyX2FmdGVyX3ByaWNlL2NvbnNvbGlkYXRlZF9wcmljaW5nX2RhdGEkcHJjLTENCmNvbHVtbnM8LWMoIkNSU1BfUGVybW5vX0lEIiwiU3RvY2tfUHJpY2VfRGF0ZSIsJ3F1YXJ0ZXJfYWZ0ZXJfcmV0dXJuJywnYW5udWFsX2FmdGVyX3JldHVybicpDQpjb25zb2xpZGF0ZWRfcHJpY2luZ19kYXRhPC1jb25zb2xpZGF0ZWRfcHJpY2luZ19kYXRhWyxjb2x1bW5zXQ0KY29uc29saWRhdGVkX3ByaWNpbmdfZGF0YQ0KYGBgDQojIFNhdmUgdGhpcyBDU1YNCmBgYHtyfQ0Kd3JpdGUuY3N2KGNvbnNvbGlkYXRlZF9wcmljaW5nX2RhdGEsImNvbnNvbGlkYXRlZF9wcmljaW5nX2RhdGEuY3N2IikNCmBgYA0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KTWVyZ2UgUHJpY2luZyBiYWNrIHRvIG91ciBvcmlnaW5hbCBjc3YgDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQpgYGB7cn0NCmNvbnNvbGlkYXRlZF9jcnNwX2NvbXB1c3RhdF9pYmVzX3ZmDQpjb25zb2xpZGF0ZWRfcHJpY2luZ19kYXRhDQpjb25zb2xpZGF0ZWRfZGF0YV92ZjwtaW5uZXJfam9pbihjb25zb2xpZGF0ZWRfY3JzcF9jb21wdXN0YXRfaWJlc192Zixjb25zb2xpZGF0ZWRfcHJpY2luZ19kYXRhLGJ5PWMoJ0NSU1BfUGVybW5vX0lEJz0nQ1JTUF9QZXJtbm9fSUQnLCdTdG9ja19QcmljZV9EYXRlJz0nU3RvY2tfUHJpY2VfRGF0ZScpKQ0KY29uc29saWRhdGVkX2RhdGFfdmYNCmBgYA0KIyBXcml0ZSB0aGlzIGludG8gY3N2IGZvcm1hdA0KYGBge3J9DQp3cml0ZS5jc3YoY29uc29saWRhdGVkX2RhdGFfdmYsImNvbnNvbGlkYXRlZF9kYXRhX3ZmLmNzdiIpDQpgYGANCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCkxvb2sgYXQgWU9ZIFJldHVybnMgDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQpgYGB7cn0NCmNvbnNvbGlkYXRlZF9kYXRhX3ZmPC1jb25zb2xpZGF0ZWRfZGF0YV92ZiU+JWRyb3BfbmEocXVhcnRlcl9hZnRlcl9yZXR1cm4sIGFubnVhbF9hZnRlcl9yZXR1cm4pDQpjb25zb2xpZGF0ZWRfZGF0YV92Zg0KYGBgDQojIEdyb3VwIGJ5IHllYXIgYW5kIHZhbHVlIGFuZCBhYm92ZSBieSBtZWRpYW4NCmBgYHtyfQ0KIyBVc2luZyBQcmljZSB0byBCb29rDQp2YWx1ZV9ieV9wcmljZV90b19ib29rX3BlcmZvcm1fYWJvdmU8LWNvbnNvbGlkYXRlZF9kYXRhX3ZmJT4lZmlsdGVyKHZhbHVlX3N0b2NrX1BCPT0xICYgYWJvdmVfZXhwZWN0YXRpb25zX21lZGlhbj09MSkNCnZhbHVlX2J5X3ByaWNlX3RvX2Jvb2tfcGVyZm9ybV9iZWxvdzwtY29uc29saWRhdGVkX2RhdGFfdmYlPiVmaWx0ZXIodmFsdWVfc3RvY2tfUEI9PTEgJiBhYm92ZV9leHBlY3RhdGlvbnNfbWVkaWFuPT0wKQ0KZ3Jvd3RoX2J5X3ByaWNlX3RvX2Jvb2tfcGVyZm9ybV9hYm92ZTwtY29uc29saWRhdGVkX2RhdGFfdmYlPiVmaWx0ZXIoZ3Jvd3RoX3N0b2NrX1BCPT0xJiBhYm92ZV9leHBlY3RhdGlvbnNfbWVkaWFuPT0xKQ0KZ3Jvd3RoX2J5X3ByaWNlX3RvX2Jvb2tfcGVyZm9ybV9iZWxvdzwtY29uc29saWRhdGVkX2RhdGFfdmYlPiVmaWx0ZXIoZ3Jvd3RoX3N0b2NrX1BCPT0xICYgYWJvdmVfZXhwZWN0YXRpb25zX21lZGlhbj09MCkNCg0KIyBVc2luZyBQcmljZSB0byBFYXJuaW5ncw0KdmFsdWVfYnlfcHJpY2VfdG9fZWFybmluZ3NfcGVyZm9ybV9hYm92ZTwtY29uc29saWRhdGVkX2RhdGFfdmYlPiVmaWx0ZXIodmFsdWVfc3RvY2tfUEU9PTEgJiBhYm92ZV9leHBlY3RhdGlvbnNfbWVkaWFuPT0xKQ0KdmFsdWVfYnlfcHJpY2VfdG9fZWFybmluZ3NfcGVyZm9ybV9iZWxvdzwtY29uc29saWRhdGVkX2RhdGFfdmYlPiVmaWx0ZXIodmFsdWVfc3RvY2tfUEU9PTEgJiBhYm92ZV9leHBlY3RhdGlvbnNfbWVkaWFuPT0wKQ0KZ3Jvd3RoX2J5X3ByaWNlX3RvX2Vhcm5pbmdzX3BlcmZvcm1fYWJvdmU8LWNvbnNvbGlkYXRlZF9kYXRhX3ZmJT4lZmlsdGVyKGdyb3d0aF9zdG9ja19QRT09MSAmIGFib3ZlX2V4cGVjdGF0aW9uc19tZWRpYW49PTEpDQpncm93dGhfYnlfcHJpY2VfdG9fZWFybmluZ3NfcGVyZm9ybV9iZWxvdzwtY29uc29saWRhdGVkX2RhdGFfdmYlPiVmaWx0ZXIoZ3Jvd3RoX3N0b2NrX1BFPT0xICYgYWJvdmVfZXhwZWN0YXRpb25zX21lZGlhbj09MCkNCg0KI0dldCB0aGUgYXZlcmFnZSByZXR1cm4gcGVyIHllYXIgYWJvdmUsIFBCIHZhbHVlDQp2YWx1ZV9ieV9wcmljZV90b19ib29rX3BlcmZvcm1fYWJvdmUkYXZlcmFnZV9xdWF0ZXJseV9yZXR1cm48LW1lYW4odmFsdWVfYnlfcHJpY2VfdG9fYm9va19wZXJmb3JtX2Fib3ZlJHF1YXJ0ZXJfYWZ0ZXJfcmV0dXJuKQ0KdmFsdWVfYnlfcHJpY2VfdG9fYm9va19wZXJmb3JtX2Fib3ZlJGF2ZXJhZ2VfYW5udWFsX3JldHVybjwtbWVhbih2YWx1ZV9ieV9wcmljZV90b19ib29rX3BlcmZvcm1fYWJvdmUkYW5udWFsX2FmdGVyX3JldHVybikNCg0KI0dldCB0aGUgYXZlcmFnZSByZXR1cm4gcGVyIHllYXIgYmVsb3csIFBCIHZhbHVlDQp2YWx1ZV9ieV9wcmljZV90b19ib29rX3BlcmZvcm1fYmVsb3ckYXZlcmFnZV9xdWF0ZXJseV9yZXR1cm48LW1lYW4odmFsdWVfYnlfcHJpY2VfdG9fYm9va19wZXJmb3JtX2JlbG93JHF1YXJ0ZXJfYWZ0ZXJfcmV0dXJuKQ0KdmFsdWVfYnlfcHJpY2VfdG9fYm9va19wZXJmb3JtX2JlbG93JGF2ZXJhZ2VfYW5udWFsX3JldHVybjwtbWVhbih2YWx1ZV9ieV9wcmljZV90b19ib29rX3BlcmZvcm1fYmVsb3ckYW5udWFsX2FmdGVyX3JldHVybikNCg0KDQojR2V0IHRoZSBhdmVyYWdlIHJldHVybiBwZXIgeWVhciBhYm92ZSwgUEIgR3Jvd3RoDQpncm93dGhfYnlfcHJpY2VfdG9fYm9va19wZXJmb3JtX2Fib3ZlJGF2ZXJhZ2VfcXVhdGVybHlfcmV0dXJuPC1tZWFuKGdyb3d0aF9ieV9wcmljZV90b19ib29rX3BlcmZvcm1fYWJvdmUkcXVhcnRlcl9hZnRlcl9yZXR1cm4pDQpncm93dGhfYnlfcHJpY2VfdG9fYm9va19wZXJmb3JtX2Fib3ZlJGF2ZXJhZ2VfYW5udWFsX3JldHVybjwtbWVhbihncm93dGhfYnlfcHJpY2VfdG9fYm9va19wZXJmb3JtX2Fib3ZlJGFubnVhbF9hZnRlcl9yZXR1cm4pDQoNCiNHZXQgdGhlIGF2ZXJhZ2UgcmV0dXJuIHBlciB5ZWFyIGJlbG93LCBQQiBHcm93dGgNCmdyb3d0aF9ieV9wcmljZV90b19ib29rX3BlcmZvcm1fYmVsb3ckYXZlcmFnZV9xdWF0ZXJseV9yZXR1cm48LW1lYW4oZ3Jvd3RoX2J5X3ByaWNlX3RvX2Jvb2tfcGVyZm9ybV9iZWxvdyRxdWFydGVyX2FmdGVyX3JldHVybikNCmdyb3d0aF9ieV9wcmljZV90b19ib29rX3BlcmZvcm1fYmVsb3ckYXZlcmFnZV9hbm51YWxfcmV0dXJuPC1tZWFuKGdyb3d0aF9ieV9wcmljZV90b19ib29rX3BlcmZvcm1fYmVsb3ckYW5udWFsX2FmdGVyX3JldHVybikNCg0KI0dldCB0aGUgYXZlcmFnZSByZXR1cm4gcGVyIHllYXIgYWJvdmUsIFBFIHZhbHVlDQp2YWx1ZV9ieV9wcmljZV90b19lYXJuaW5nc19wZXJmb3JtX2Fib3ZlJGF2ZXJhZ2VfcXVhdGVybHlfcmV0dXJuPC1tZWFuKHZhbHVlX2J5X3ByaWNlX3RvX2Vhcm5pbmdzX3BlcmZvcm1fYWJvdmUkcXVhcnRlcl9hZnRlcl9yZXR1cm4pDQp2YWx1ZV9ieV9wcmljZV90b19lYXJuaW5nc19wZXJmb3JtX2Fib3ZlJGF2ZXJhZ2VfYW5udWFsX3JldHVybjwtbWVhbih2YWx1ZV9ieV9wcmljZV90b19lYXJuaW5nc19wZXJmb3JtX2Fib3ZlJGFubnVhbF9hZnRlcl9yZXR1cm4pDQoNCiNHZXQgdGhlIGF2ZXJhZ2UgcmV0dXJuIHBlciB5ZWFyIGJlbG93LCBQQiB2YWx1ZQ0KdmFsdWVfYnlfcHJpY2VfdG9fZWFybmluZ3NfcGVyZm9ybV9iZWxvdyRhdmVyYWdlX3F1YXRlcmx5X3JldHVybjwtbWVhbih2YWx1ZV9ieV9wcmljZV90b19lYXJuaW5nc19wZXJmb3JtX2JlbG93JHF1YXJ0ZXJfYWZ0ZXJfcmV0dXJuKQ0KdmFsdWVfYnlfcHJpY2VfdG9fZWFybmluZ3NfcGVyZm9ybV9iZWxvdyRhdmVyYWdlX2FubnVhbF9yZXR1cm48LW1lYW4odmFsdWVfYnlfcHJpY2VfdG9fZWFybmluZ3NfcGVyZm9ybV9iZWxvdyRhbm51YWxfYWZ0ZXJfcmV0dXJuKQ0KDQojR2V0IHRoZSBhdmVyYWdlIHJldHVybiBwZXIgeWVhciBhYm92ZSwgUEIgR3Jvd3RoDQpncm93dGhfYnlfcHJpY2VfdG9fZWFybmluZ3NfcGVyZm9ybV9hYm92ZSRhdmVyYWdlX3F1YXRlcmx5X3JldHVybjwtbWVhbihncm93dGhfYnlfcHJpY2VfdG9fZWFybmluZ3NfcGVyZm9ybV9hYm92ZSRxdWFydGVyX2FmdGVyX3JldHVybikNCmdyb3d0aF9ieV9wcmljZV90b19lYXJuaW5nc19wZXJmb3JtX2Fib3ZlJGF2ZXJhZ2VfYW5udWFsX3JldHVybjwtbWVhbihncm93dGhfYnlfcHJpY2VfdG9fZWFybmluZ3NfcGVyZm9ybV9hYm92ZSRhbm51YWxfYWZ0ZXJfcmV0dXJuKQ0KDQojR2V0IHRoZSBhdmVyYWdlIHJldHVybiBwZXIgeWVhciBiZWxvdywgUEIgR3Jvd3RoDQpncm93dGhfYnlfcHJpY2VfdG9fZWFybmluZ3NfcGVyZm9ybV9iZWxvdyRhdmVyYWdlX3F1YXRlcmx5X3JldHVybjwtbWVhbihncm93dGhfYnlfcHJpY2VfdG9fZWFybmluZ3NfcGVyZm9ybV9iZWxvdyRxdWFydGVyX2FmdGVyX3JldHVybikNCmdyb3d0aF9ieV9wcmljZV90b19lYXJuaW5nc19wZXJmb3JtX2JlbG93JGF2ZXJhZ2VfYW5udWFsX3JldHVybjwtbWVhbihncm93dGhfYnlfcHJpY2VfdG9fZWFybmluZ3NfcGVyZm9ybV9iZWxvdyRhbm51YWxfYWZ0ZXJfcmV0dXJuKQ0KDQojT3V0cHV0IFJlc3VsdHMgUC9CDQp2YWx1ZV9ieV9wcmljZV90b19ib29rX3BlcmZvcm1fYWJvdmUNCnZhbHVlX2J5X3ByaWNlX3RvX2Jvb2tfcGVyZm9ybV9iZWxvdw0KZ3Jvd3RoX2J5X3ByaWNlX3RvX2Jvb2tfcGVyZm9ybV9hYm92ZQ0KZ3Jvd3RoX2J5X3ByaWNlX3RvX2Jvb2tfcGVyZm9ybV9iZWxvdw0KDQojT3V0cHV0IFJlc3VsdHMgUC9FDQp2YWx1ZV9ieV9wcmljZV90b19lYXJuaW5nc19wZXJmb3JtX2Fib3ZlDQp2YWx1ZV9ieV9wcmljZV90b19lYXJuaW5nc19wZXJmb3JtX2JlbG93DQpncm93dGhfYnlfcHJpY2VfdG9fZWFybmluZ3NfcGVyZm9ybV9hYm92ZQ0KZ3Jvd3RoX2J5X3ByaWNlX3RvX2Vhcm5pbmdzX3BlcmZvcm1fYmVsb3cNCmBgYA0KIyBDb25jYXQgdGhpcyB0byBnZXQganVzdCBvbmUgdmFsdWUgDQpgYGB7cn0NCnZhbHVlX2J5X3ByaWNlX3RvX2Jvb2tfcGVyZm9ybV9hYm92ZV9zdW1tYXJ5PC12YWx1ZV9ieV9wcmljZV90b19ib29rX3BlcmZvcm1fYWJvdmUlPiVkaXN0aW5jdChGaXNjYWxfWWVhciwua2VlcF9hbGwgPSBUUlVFKQ0KdmFsdWVfYnlfcHJpY2VfdG9fYm9va19wZXJmb3JtX2JlbG93X3N1bW1hcnk8LXZhbHVlX2J5X3ByaWNlX3RvX2Jvb2tfcGVyZm9ybV9iZWxvdyU+JWRpc3RpbmN0KEZpc2NhbF9ZZWFyLC5rZWVwX2FsbCA9IFRSVUUpDQpncm93dGhfYnlfcHJpY2VfdG9fYm9va19wZXJmb3JtX2Fib3ZlX3N1bW1hcnk8LWdyb3d0aF9ieV9wcmljZV90b19ib29rX3BlcmZvcm1fYWJvdmUlPiVkaXN0aW5jdChGaXNjYWxfWWVhciwua2VlcF9hbGwgPSBUUlVFKQ0KZ3Jvd3RoX2J5X3ByaWNlX3RvX2Jvb2tfcGVyZm9ybV9iZWxvd19zdW1tYXJ5PC1ncm93dGhfYnlfcHJpY2VfdG9fYm9va19wZXJmb3JtX2JlbG93JT4lZGlzdGluY3QoRmlzY2FsX1llYXIsLmtlZXBfYWxsID0gVFJVRSkNCg0KdmFsdWVfYnlfcHJpY2VfdG9fYm9va19wZXJmb3JtX2Fib3ZlX3N1bW1hcnk8LWFycmFuZ2UodmFsdWVfYnlfcHJpY2VfdG9fYm9va19wZXJmb3JtX2Fib3ZlX3N1bW1hcnksRmlzY2FsX1llYXIpDQp2YWx1ZV9ieV9wcmljZV90b19ib29rX3BlcmZvcm1fYmVsb3dfc3VtbWFyeTwtYXJyYW5nZSh2YWx1ZV9ieV9wcmljZV90b19ib29rX3BlcmZvcm1fYmVsb3dfc3VtbWFyeSxGaXNjYWxfWWVhcikNCmdyb3d0aF9ieV9wcmljZV90b19ib29rX3BlcmZvcm1fYWJvdmVfc3VtbWFyeTwtYXJyYW5nZShncm93dGhfYnlfcHJpY2VfdG9fYm9va19wZXJmb3JtX2Fib3ZlX3N1bW1hcnksRmlzY2FsX1llYXIpDQpncm93dGhfYnlfcHJpY2VfdG9fYm9va19wZXJmb3JtX2JlbG93X3N1bW1hcnk8LWFycmFuZ2UoZ3Jvd3RoX2J5X3ByaWNlX3RvX2Jvb2tfcGVyZm9ybV9iZWxvd19zdW1tYXJ5LEZpc2NhbF9ZZWFyKQ0KDQphZ2dyZWdhdGVfcHJpY2VfdG9fYm9vazwtcmJpbmQodmFsdWVfYnlfcHJpY2VfdG9fYm9va19wZXJmb3JtX2Fib3ZlX3N1bW1hcnksdmFsdWVfYnlfcHJpY2VfdG9fYm9va19wZXJmb3JtX2JlbG93X3N1bW1hcnksZ3Jvd3RoX2J5X3ByaWNlX3RvX2Jvb2tfcGVyZm9ybV9hYm92ZV9zdW1tYXJ5LGdyb3d0aF9ieV9wcmljZV90b19ib29rX3BlcmZvcm1fYmVsb3dfc3VtbWFyeSkNCmFnZ3JlZ2F0ZV9wcmljZV90b19ib29rPC1hZ2dyZWdhdGVfcHJpY2VfdG9fYm9vayU+JWdyb3VwX2J5KEZpc2NhbF9ZZWFyKQ0KYWdncmVnYXRlX3ByaWNlX3RvX2Jvb2s8LWFycmFuZ2UoYWdncmVnYXRlX3ByaWNlX3RvX2Jvb2ssRmlzY2FsX1llYXIpDQoNCnZhbHVlX2J5X3ByaWNlX3RvX2Jvb2tfcGVyZm9ybV9hYm92ZV9zdW1tYXJ5DQoNCmBgYA0KIyBDb25jYXQgdGhpcyB0byBnZXQganVzdCBvbmUgdmFsdWUgDQpgYGB7cn0NCnZhbHVlX2J5X3ByaWNlX3RvX2Vhcm5pbmdzX3BlcmZvcm1fYWJvdmVfc3VtbWFyeTwtdmFsdWVfYnlfcHJpY2VfdG9fZWFybmluZ3NfcGVyZm9ybV9hYm92ZSU+JWRpc3RpbmN0KEZpc2NhbF9ZZWFyLC5rZWVwX2FsbCA9IFRSVUUpDQp2YWx1ZV9ieV9wcmljZV90b19lYXJuaW5nc19wZXJmb3JtX2JlbG93X3N1bW1hcnk8LXZhbHVlX2J5X3ByaWNlX3RvX2Vhcm5pbmdzX3BlcmZvcm1fYmVsb3clPiVkaXN0aW5jdChGaXNjYWxfWWVhciwua2VlcF9hbGwgPSBUUlVFKQ0KZ3Jvd3RoX2J5X3ByaWNlX3RvX2Vhcm5pbmdzX3BlcmZvcm1fYWJvdmVfc3VtbWFyeTwtZ3Jvd3RoX2J5X3ByaWNlX3RvX2Vhcm5pbmdzX3BlcmZvcm1fYWJvdmUlPiVkaXN0aW5jdChGaXNjYWxfWWVhciwua2VlcF9hbGwgPSBUUlVFKQ0KZ3Jvd3RoX2J5X3ByaWNlX3RvX2Vhcm5pbmdzX3BlcmZvcm1fYmVsb3dfc3VtbWFyeTwtZ3Jvd3RoX2J5X3ByaWNlX3RvX2Vhcm5pbmdzX3BlcmZvcm1fYmVsb3clPiVkaXN0aW5jdChGaXNjYWxfWWVhciwua2VlcF9hbGwgPSBUUlVFKQ0KDQp2YWx1ZV9ieV9wcmljZV90b19lYXJuaW5nc19wZXJmb3JtX2Fib3ZlX3N1bW1hcnk8LWFycmFuZ2UodmFsdWVfYnlfcHJpY2VfdG9fZWFybmluZ3NfcGVyZm9ybV9hYm92ZV9zdW1tYXJ5LEZpc2NhbF9ZZWFyKQ0KdmFsdWVfYnlfcHJpY2VfdG9fZWFybmluZ3NfcGVyZm9ybV9iZWxvd19zdW1tYXJ5PC1hcnJhbmdlKHZhbHVlX2J5X3ByaWNlX3RvX2Vhcm5pbmdzX3BlcmZvcm1fYmVsb3dfc3VtbWFyeSxGaXNjYWxfWWVhcikNCmdyb3d0aF9ieV9wcmljZV90b19lYXJuaW5nc19wZXJmb3JtX2Fib3ZlX3N1bW1hcnk8LWFycmFuZ2UoZ3Jvd3RoX2J5X3ByaWNlX3RvX2Vhcm5pbmdzX3BlcmZvcm1fYWJvdmVfc3VtbWFyeSxGaXNjYWxfWWVhcikNCmdyb3d0aF9ieV9wcmljZV90b19lYXJuaW5nc19wZXJmb3JtX2JlbG93X3N1bW1hcnk8LWFycmFuZ2UoZ3Jvd3RoX2J5X3ByaWNlX3RvX2Vhcm5pbmdzX3BlcmZvcm1fYmVsb3dfc3VtbWFyeSxGaXNjYWxfWWVhcikNCg0KYWdncmVnYXRlX3ByaWNlX3RvX2Vhcm5pbmdzPC1yYmluZCh2YWx1ZV9ieV9wcmljZV90b19lYXJuaW5nc19wZXJmb3JtX2Fib3ZlX3N1bW1hcnksdmFsdWVfYnlfcHJpY2VfdG9fZWFybmluZ3NfcGVyZm9ybV9iZWxvd19zdW1tYXJ5LGdyb3d0aF9ieV9wcmljZV90b19lYXJuaW5nc19wZXJmb3JtX2Fib3ZlX3N1bW1hcnksZ3Jvd3RoX2J5X3ByaWNlX3RvX2Vhcm5pbmdzX3BlcmZvcm1fYmVsb3dfc3VtbWFyeSkNCmFnZ3JlZ2F0ZV9wcmljZV90b19lYXJuaW5nczwtYWdncmVnYXRlX3ByaWNlX3RvX2Vhcm5pbmdzJT4lZ3JvdXBfYnkoRmlzY2FsX1llYXIpDQphZ2dyZWdhdGVfcHJpY2VfdG9fZWFybmluZ3M8LWFycmFuZ2UoYWdncmVnYXRlX3ByaWNlX3RvX2Vhcm5pbmdzLEZpc2NhbF9ZZWFyKQ0KYWdncmVnYXRlX3ByaWNlX3RvX2Vhcm5pbmdzDQpgYGANCiMgTWFrZSBhIGZvciBhZ2dyZWdhdGUgcmV0dXJucyBnaXZlbiBwcmljZSB0byBlYXJuaW5ncw0KYGBge3J9DQphZ2dyZWdhdGVfcHJpY2VfdG9fZWFybmluZ3MkdHlwZV9vZl9zZWN1cml0eV9QQjwtIk5BIg0KYWdncmVnYXRlX3ByaWNlX3RvX2Vhcm5pbmdzJHR5cGVfb2Zfc2VjdXJpdHlfUEJbYWdncmVnYXRlX3ByaWNlX3RvX2Vhcm5pbmdzJHZhbHVlX3N0b2NrX1BCPT0xJmFnZ3JlZ2F0ZV9wcmljZV90b19lYXJuaW5ncyRhYm92ZV9leHBlY3RhdGlvbnNfbWVkaWFuPT0xXTwtIlZhbHVlIFN0b2NrIEFib3ZlIEV4cGVjdGF0aW9ucyINCmFnZ3JlZ2F0ZV9wcmljZV90b19lYXJuaW5ncyR0eXBlX29mX3NlY3VyaXR5X1BCW2FnZ3JlZ2F0ZV9wcmljZV90b19lYXJuaW5ncyR2YWx1ZV9zdG9ja19QQj09MSZhZ2dyZWdhdGVfcHJpY2VfdG9fZWFybmluZ3MkYWJvdmVfZXhwZWN0YXRpb25zX21lZGlhbj09MF08LSJWYWx1ZSBTdG9jayBCZWxvdyBFeHBlY3RhdGlvbnMiDQphZ2dyZWdhdGVfcHJpY2VfdG9fZWFybmluZ3MkdHlwZV9vZl9zZWN1cml0eV9QQlthZ2dyZWdhdGVfcHJpY2VfdG9fZWFybmluZ3MkZ3Jvd3RoX3N0b2NrX1BCPT0xJmFnZ3JlZ2F0ZV9wcmljZV90b19lYXJuaW5ncyRhYm92ZV9leHBlY3RhdGlvbnNfbWVkaWFuPT0xXTwtIkdyb3d0aCBTdG9jayBBYm92ZSBFeHBlY3RhdGlvbnMiDQphZ2dyZWdhdGVfcHJpY2VfdG9fZWFybmluZ3MkdHlwZV9vZl9zZWN1cml0eV9QQlthZ2dyZWdhdGVfcHJpY2VfdG9fZWFybmluZ3MkZ3Jvd3RoX3N0b2NrX1BCPT0xJmFnZ3JlZ2F0ZV9wcmljZV90b19lYXJuaW5ncyRhYm92ZV9leHBlY3RhdGlvbnNfbWVkaWFuPT0wXTwtIkdyb3d0aCBTdG9jayBCZWxvdyBFeHBlY3RhdGlvbnMiDQoNCmFnZ3JlZ2F0ZV9wcmljZV90b19lYXJuaW5ncyR0eXBlX29mX3NlY3VyaXR5X1BFPC0iTkEiDQphZ2dyZWdhdGVfcHJpY2VfdG9fZWFybmluZ3MkdHlwZV9vZl9zZWN1cml0eV9QRVthZ2dyZWdhdGVfcHJpY2VfdG9fZWFybmluZ3MkdmFsdWVfc3RvY2tfUEU9PTEmYWdncmVnYXRlX3ByaWNlX3RvX2Vhcm5pbmdzJGFib3ZlX2V4cGVjdGF0aW9uc19tZWRpYW49PTFdPC0iVmFsdWUgU3RvY2sgQWJvdmUgRXhwZWN0YXRpb25zIg0KYWdncmVnYXRlX3ByaWNlX3RvX2Vhcm5pbmdzJHR5cGVfb2Zfc2VjdXJpdHlfUEVbYWdncmVnYXRlX3ByaWNlX3RvX2Vhcm5pbmdzJGdyb3d0aF9zdG9ja19QRT09MSZhZ2dyZWdhdGVfcHJpY2VfdG9fZWFybmluZ3MkYWJvdmVfZXhwZWN0YXRpb25zX21lZGlhbj09MV08LSJHcm93dGggU3RvY2sgQWJvdmUgRXhwZWN0YXRpb25zIg0KYWdncmVnYXRlX3ByaWNlX3RvX2Vhcm5pbmdzJHR5cGVfb2Zfc2VjdXJpdHlfUEVbYWdncmVnYXRlX3ByaWNlX3RvX2Vhcm5pbmdzJHZhbHVlX3N0b2NrX1BFPT0xJmFnZ3JlZ2F0ZV9wcmljZV90b19lYXJuaW5ncyRhYm92ZV9leHBlY3RhdGlvbnNfbWVkaWFuPT0wXTwtIlZhbHVlIFN0b2NrIEJlbG93IEV4cGVjdGF0aW9ucyINCmFnZ3JlZ2F0ZV9wcmljZV90b19lYXJuaW5ncyR0eXBlX29mX3NlY3VyaXR5X1BFW2FnZ3JlZ2F0ZV9wcmljZV90b19lYXJuaW5ncyRncm93dGhfc3RvY2tfUEU9PTEmYWdncmVnYXRlX3ByaWNlX3RvX2Vhcm5pbmdzJGFib3ZlX2V4cGVjdGF0aW9uc19tZWRpYW49PTBdPC0iR3Jvd3RoIFN0b2NrIEJlbG93IEV4cGVjdGF0aW9ucyINCmBgYA0KIyBNdXRhdGUgdGhlIGRhdGEgc28gd2UgY2FuIHdvcmsgd2l0aCBpdCANCmBgYHtyfQ0KY29sdW1uczwtYygnRmlzY2FsX1llYXInLCdxdWFydGVyX2FmdGVyX3JldHVybicsJ2FubnVhbF9hZnRlcl9yZXR1cm4nLCd0eXBlX29mX3NlY3VyaXR5X1BCJywndHlwZV9vZl9zZWN1cml0eV9QRScpDQphZ2dyZWdhdGVfcHJpY2VfdG9fZWFybmluZ3NfdjE8LWFnZ3JlZ2F0ZV9wcmljZV90b19lYXJuaW5nc1ssY29sdW1uc10NCmFnZ3JlZ2F0ZV9wcmljZV90b19lYXJuaW5nc192MQ0KYGBgDQojV3JpdGUgaW50byBFeGNlbA0KYGBge3J9DQp3cml0ZS5jc3YodmFsdWVfYnlfcHJpY2VfdG9fYm9va19wZXJmb3JtX2Fib3ZlX3N1bW1hcnksInZhbHVlX2J5X3ByaWNlX3RvX2Jvb2tfcGVyZm9ybV9hYm92ZV9zdW1tYXJ5LmNzdiIpDQp3cml0ZS5jc3YodmFsdWVfYnlfcHJpY2VfdG9fYm9va19wZXJmb3JtX2JlbG93X3N1bW1hcnksInZhbHVlX2J5X3ByaWNlX3RvX2Jvb2tfcGVyZm9ybV9iZWxvd19zdW1tYXJ5LmNzdiIpDQp3cml0ZS5jc3YoZ3Jvd3RoX2J5X3ByaWNlX3RvX2Jvb2tfcGVyZm9ybV9hYm92ZV9zdW1tYXJ5LCJncm93dGhfYnlfcHJpY2VfdG9fYm9va19wZXJmb3JtX2Fib3ZlX3N1bW1hcnkuY3N2IikNCndyaXRlLmNzdihncm93dGhfYnlfcHJpY2VfdG9fYm9va19wZXJmb3JtX2JlbG93X3N1bW1hcnksImdyb3d0aF9ieV9wcmljZV90b19ib29rX3BlcmZvcm1fYmVsb3dfc3VtbWFyeS5jc3YiKQ0KDQp3cml0ZS5jc3YodmFsdWVfYnlfcHJpY2VfdG9fZWFybmluZ3NfcGVyZm9ybV9hYm92ZV9zdW1tYXJ5LCJ2YWx1ZV9ieV9wcmljZV90b19lYXJuaW5nc19wZXJmb3JtX2Fib3ZlX3N1bW1hcnkuY3N2IikNCndyaXRlLmNzdih2YWx1ZV9ieV9wcmljZV90b19lYXJuaW5nc19wZXJmb3JtX2JlbG93X3N1bW1hcnksInZhbHVlX2J5X3ByaWNlX3RvX2Vhcm5pbmdzX3BlcmZvcm1fYmVsb3dfc3VtbWFyeS5jc3YiKQ0Kd3JpdGUuY3N2KGdyb3d0aF9ieV9wcmljZV90b19lYXJuaW5nc19wZXJmb3JtX2Fib3ZlX3N1bW1hcnksImdyb3d0aF9ieV9wcmljZV90b19lYXJuaW5nc19wZXJmb3JtX2Fib3ZlX3N1bW1hcnkuY3N2IikNCndyaXRlLmNzdihncm93dGhfYnlfcHJpY2VfdG9fZWFybmluZ3NfcGVyZm9ybV9iZWxvd19zdW1tYXJ5LCJncm93dGhfYnlfcHJpY2VfdG9fZWFybmluZ3NfcGVyZm9ybV9iZWxvd19zdW1tYXJ5LmNzdiIpDQoNCmBgYA0KDQo=